/****************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = sqlserver_common.c                                            */
/*  NOTE      = TDS 请求解析                                                  */
/*  DATE      = 2014/09/30 by zhengxd                                         */
/****************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <stdint.h>
#include <limits.h>

#include "sqlserver_base_type.h"
#include "sqlserver_token.h"
#include "sqlserver_common.h"

#if defined(FRLINUX4) || defined(FRLINUX5)
#define ULLONG_MAX 18446744073709551615ULL
#endif

/* 0001年1月1号到1970年一月一号相隔的天数 */
#define TDS_0001_1970_DAYS                719162
/* 4位最大整数 */
#define MSSQL_4BYTE_MAX_VALUE             "4294967296"
/* 8位最大整数 */
#define MSSQL_8BYTE_MAX_VALUE             "18446744073709551616"
/* 12位最大整数 */
#define MSSQL_12BYTE_MAX_VALUE            "340282366920938463463374607431768211456"
/* 16位最大整数的值为115792089237316195423570985008687907853269984665640564039457584007913129639935，长度78 */
#define MSSQL_16BYTE_MAX_LEN              78

#define MSSQL_BLOB_DATA                   "BLOB_DATA"

/* PRELOGIN 类型 */
#define MSSQL_PRELOGIN_VERSION      0
#define MSSQL_PRELOGIN_ENCRYPTION   1
#define MSSQL_PRELOGIN_INSTOPT      2
#define MSSQL_PRELOGIN_THREADID     3
#define MSSQL_PRELOGIN_MARS         4
#define MSSQL_PRELOGIN_TRACEID      5
#define MSSQL_PRELOGIN_FEDAUTH      6
#define MSSQL_PRELOGIN_NONCEOPT     7
#define MSSQL_PRELOGIN_TERMINATOR   255
#define MSSQL_REPORT_KEY_DBNAME     APM_REPORT_KEY_SESSION".mmsql.dbname"

union int32_float_bits {
    int32_t int_bits;
    float float_bits;
};

union int64_double_bits {
    int64_t int_bits;
    double double_bits;
};

/* METADATA token 数据类型 */
typedef struct __st_mssql_perlogin_token
{
    unsigned char uc_token_type;
    unsigned short us_offset;
    unsigned short us_length;
} Mssql_perlogin_token;

/*******************************************************************************
*  FUNC     :  取得prelogin的offset+length
*  ARGS     :  p_st_data(入力数据)
*           :  uc_token_type(prelogin token)
*           :  p_i_ssl_flg(SLL flag)
*           :  p_lst_header(token list)
*  RTN      :  0       (true)
*              1       (false)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __sqlserver_get_token_lst(Frbyte_Packet *p_st_data
                                    , unsigned char uc_token_type
                                    , int *p_i_ssl_flg
                                    , Frlist_header *p_lst_header)
{
    int i_ret = FR_SUCC;
    unsigned short us_offset = 0;
    unsigned short us_length = 0;
    Frlist_node *p_st_node = NULL;
    Mssql_perlogin_token *p_st_token = NULL;

    /* offset和length都是是USHORT */
    if (bytebuff_remaining(p_st_data) < MSSQL_TDS_USHORT_LEN + MSSQL_TDS_USHORT_LEN)
    {
        *p_i_ssl_flg = FR_YES;
        return FR_SUCC;
    }

    /* 取得offset和length的值 */
    i_ret = bytebuff_get_short(p_st_data, MSSQL_TDS_USHORT_LEN
                               , &us_offset, BYTE_LITTLE_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return FR_FAIL;
    }
    i_ret = bytebuff_get_short(p_st_data, MSSQL_TDS_USHORT_LEN
                               , &us_length, BYTE_LITTLE_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return FR_FAIL;
    }

    /* 做成节点 */
    p_st_token = (Mssql_perlogin_token *)frmalloc(sizeof(Mssql_perlogin_token));
    if (p_st_token == NULL)
    {
        return FR_FAIL;
    }
    p_st_token->uc_token_type = uc_token_type;
    p_st_token->us_offset = us_offset;
    p_st_token->us_length = us_length;

    /* 做成节点 */
    p_st_node = frlist_node_create(p_st_token);
    if (p_st_node == NULL)
    {
        frfree(p_st_token);
    }
    frlist_push(p_lst_header, p_st_node);
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  free list
*  ARGS     :  pp_lst_header(token list)
*  RTN      :  0       (true)
*              1       (false)
*  NOTE     :
*******************************************************************************/
FR_STATIC void __sqlserver_token_node_free(Frlist_node *p_st_node)
{
    if( p_st_node == NULL || p_st_node->data == NULL)
    {
        return;
    }

    frfree(p_st_node->data);
    return;
}

/*******************************************************************************
*  FUNC     :  altmetadata节点释放函数
*  ARGS     :  p_st_node (altmetadata节点)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void sqlserver_altmetadata_node_free(Frlist_node *p_st_node)
{
    if( p_st_node == NULL || p_st_node->data == NULL)
    {
        return;
    }

    Mssql_altmetadata_info *p_st_altmetadata = (Mssql_altmetadata_info *)p_st_node->data;
    frlist_destroy(p_st_altmetadata->p_lst_metadata, frdb_metadata_node_free);
    frfree(p_st_altmetadata);
    return;
}

/*******************************************************************************
*  FUNC     :  将data追加到frlist
*  ARGS     :  p_list_header (List header)
*           :  p_data (数据)
*  RTN      :  FR_SUCC  (success)
*              FR_FAIL  (failed)
*  NOTE     :  p_list_header必须不为NULL
*******************************************************************************/
int sqlserver_data_push(Frlist_header *p_list_header, void *p_data)
{
    Frlist_node *p_st_node = NULL;

    /* 创建node */
    p_st_node = frlist_node_create(p_data);
    if (p_st_node == NULL)
    {
        return FR_FAIL;
    }

    frlist_push(p_list_header, p_st_node);
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  释放内存
*  ARGS     :  pp_buffer
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void sqlserver_node_free(Frlist_node *p_st_node)
{
    if( p_st_node == NULL || p_st_node->data == NULL)
    {
        return;
    }

    frfree(p_st_node->data);

    return;
}

/*******************************************************************************
*  FUNC     :  释放内存
*  ARGS     :  pp_buffer
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void sqlserver_free(void **pp_buffer)
{
    if (pp_buffer == NULL || *pp_buffer == NULL)
    {
        return;
    }

    frfree(*pp_buffer);
    *pp_buffer = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  bind参数节点释放
*  ARGS     :  p_st_node(bind参数节点)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void sqlserver_parameter_free(Frlist_node *p_st_node)
{
    if( p_st_node == NULL || p_st_node->data == NULL)
    {
        return;
    }

    frfree(p_st_node->data);
    p_st_node->data = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  frhead节点free
*  ARGS     :  p_st_node(bind参数节点)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void sqlserver_list_free(Frlist_node *p_st_node)
{
    if( p_st_node == NULL || p_st_node->data == NULL)
    {
        return;
    }

    Frlist_header *p_lst_header = (Frlist_header *)p_st_node->data;
    frlist_destroy(p_lst_header, sqlserver_frdata_node_free);

    return;
}

/*******************************************************************************
*  FUNC     :  request信息释放
*  ARGS     :  pp_st_request(request信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void sqlserver_destroy_request(L7_req_sqlserver **pp_st_request)
{
    if(pp_st_request == NULL || *pp_st_request == NULL)
    {
        return;
    }

    L7_req_sqlserver *p_st_request = *pp_st_request;

    if (!(p_st_request->u8_request_type == MSSQL_TDS_RPCREQUEST
        && (p_st_request->u16_rpc_type == MSSQL_PREPARE_CURSOR
            || p_st_request->u16_rpc_type == MSSQL_PREPARE_CURSOR_OPEN
            || p_st_request->u16_rpc_type == MSSQL_PREPARE_CURSOR_EXECUTE
            || p_st_request->u16_rpc_type == MSSQL_PREPARE_CURSOR_UNPREPARE
            || p_st_request->u16_rpc_type == MSSQL_PREPARE_CURSOR_FETCH
            || p_st_request->u16_rpc_type == MSSQL_PREPARE_CURSOR_OPTION
            || p_st_request->u16_rpc_type == MSSQL_PREPARE_CURSOR_CLOSE
            || p_st_request->u16_rpc_type == MSSQL_PREPARE_EXECUTE_SQL
            || p_st_request->u16_rpc_type == MSSQL_PREPARE_EXECUTE
            || p_st_request->u16_rpc_type == MSSQL_PREPARE_PREPEXECRPC
            || p_st_request->u16_rpc_type == MSSQL_PREPARE_UNPREPARE)))
    {
        /* 释放SQL statement信息 */
        frdb_statement_free(&(p_st_request->p_st_statement));
    }

    frfree(p_st_request);
    *pp_st_request = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  resposne信息初始化
*  ARGS     :  pp_st_request(request信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void sqlserver_init_response(L7_resp_sqlserver *p_st_resp
                            , int i_tds_ver
                            , int i_tds_min_ver
                            , int i_tds_max_ver)
{
    if (p_st_resp == NULL)
    {
        return;
    }

    /* 释放charset */
    if (p_st_resp->p_charset)
    {
        frfree(p_st_resp->p_charset);
    }
    /* 释放error message */
    if (p_st_resp->p_error_msg)
    {
        frfree(p_st_resp->p_error_msg);
    }
    /* 释放altmetadata */
    frlist_remove_all(&(p_st_resp->st_altmetadata_header)
                     , sqlserver_altmetadata_node_free);
    /* 释放colmetadata */
    frlist_remove_all(&(p_st_resp->st_colmetadata_header)
                     , frdb_metadata_node_free);

    /* 初始化response信息 */
    memset(p_st_resp, 0x0, sizeof(L7_resp_sqlserver));
    //p_st_resp->i_first_return_value = FR_YES;
    p_st_resp->i_ser_tds_ver_tmp = i_tds_ver;
    p_st_resp->i_ser_tds_min_ver_tmp = i_tds_min_ver;
    p_st_resp->i_ser_tds_max_ver_tmp = i_tds_max_ver;

    return;
}

/*******************************************************************************
*  FUNC     :  resposne信息释放
*  ARGS     :  pp_st_request(request信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void sqlserver_destroy_response(L7_resp_sqlserver **pp_st_resp)
{
    if (pp_st_resp == NULL || *pp_st_resp == NULL)
    {
        return;
    }

    L7_resp_sqlserver *p_st_resp = *pp_st_resp;

    /* 释放charset */
    if (p_st_resp->p_charset)
    {
        frfree(p_st_resp->p_charset);
    }
    /* 释放error message */
    if (p_st_resp->p_error_msg)
    {
        frfree(p_st_resp->p_error_msg);
    }
    /* 释放altmetadata */
    frlist_remove_all(&(p_st_resp->st_altmetadata_header)
                     , sqlserver_altmetadata_node_free);
    /* 释放colmetadata */
    frlist_remove_all(&(p_st_resp->st_colmetadata_header)
                     , frdb_metadata_node_free);

    frfree(p_st_resp);
    *pp_st_resp = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  释放分片包信息
*  ARGS     :  pp_st_fragment (分片包信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void sqlserver_init_fragment(L7_fragment_sqlserver *p_st_fragment)
{
    if (p_st_fragment == NULL)
    {
        return;
    }

    if (p_st_fragment->p_st_data)
    {
        bytebuff_free(&p_st_fragment->p_st_data);
    }
    memset(p_st_fragment, 0x0, sizeof(L7_fragment_sqlserver));

    return;
}

/*******************************************************************************
*  FUNC     :  释放分片包信息
*  ARGS     :  pp_st_fragment (分片包信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void sqlserver_destroy_fragment(L7_fragment_sqlserver **pp_st_fragment)
{
    if (pp_st_fragment == NULL || *pp_st_fragment == NULL)
    {
        return;
    }

    L7_fragment_sqlserver *p_st_fragment = *pp_st_fragment;
    if (p_st_fragment->p_st_data)
    {
        bytebuff_free(&p_st_fragment->p_st_data);
    }
    frfree(p_st_fragment);

    *pp_st_fragment = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  解析PRE LOGIN信息
*  ARGS     :  p_st_session(入力链接信息)
*           :  p_inbuffer(入力packet信息)
*           :  ui_buffer_len(入力packet信息长度)
*           :  i_ser_cli_flg(是客户端的还是服务端的)
*  RTN      :  0       (true)
*              1       (false)
*  NOTE     :
*******************************************************************************/
int sqlserver_parse_prelogin(Conntrack *p_st_conn
                            , L7session_sqlserver_private *p_st_private
                            , Frhash_header *p_st_hash_report
                            , int i_whole_flg
                            , int i_ser_cli_flg)
{
    /* pre login中不会出现大数据,接受完了之后再解析 */
    if (i_whole_flg != FR_YES)
    {
        return APM_L7_ANALYZE_TODO;
    }

    /* 定义：可以是login的上下文也可以是SSL handshake payload
    * PRELOGIN = (*PRELOGIN_OPTION
    *             *PL_OPTION_DATA)
    *             /
    *             SSL_PAYLOAD
    * PRELOGIN_OPTION = (PL_OPTION_TOKEN
    *                    PL_OFFSET
    *                    PL_OPTION_LENGTH)
    *                    /
    *                    TERMINATOR
    * PL_OPTION_DATA = *BYTE ; actual data for the option
    * SSL_PAYLOAD = *BYTE ; SSL handshake raw payload
    */

    /* 现今只是做相当于只是做了check，对于解密工作暂时不做 */
    int i_ret = FR_SUCC;
    int i_ssl_flg = FR_NO;
    unsigned char uc_prelogin_token = 0;
    unsigned short us_offset = 0;
    unsigned short us_length = 0;
    unsigned int ui_buffer_len = 0;
    Frlist_header st_header;
    memset(&st_header, 0x0, sizeof(Frlist_header));
    Frlist_node *p_st_node = NULL;
    Mssql_perlogin_token *p_st_token = NULL;
    L7_req_sqlserver *p_st_req = NULL;
    L7_fragment_sqlserver *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 取得解析位置 */
    ui_buffer_len = bytebuff_remaining(p_st_data);

    /* 先用login上下文尝试解析，格式错误视该段为SSL handshake payload */
    while (bytebuff_remaining(p_st_data))
    {
        bytebuff_get_char(p_st_data, &uc_prelogin_token);
        /* 取得每个token的offse和长度 */
        switch (uc_prelogin_token)
        {
            case MSSQL_PRELOGIN_VERSION:
            case MSSQL_PRELOGIN_ENCRYPTION:
            case MSSQL_PRELOGIN_INSTOPT:
            case MSSQL_PRELOGIN_THREADID:
            case MSSQL_PRELOGIN_MARS:
            case MSSQL_PRELOGIN_TRACEID:
            case MSSQL_PRELOGIN_FEDAUTH:
            case MSSQL_PRELOGIN_NONCEOPT:
                i_ret = __sqlserver_get_token_lst(p_st_data, uc_prelogin_token
                                                 , &i_ssl_flg, &st_header);
                if (i_ret != FR_SUCC)
                {
                    frlist_remove_all(&st_header, __sqlserver_token_node_free);
                    return APM_L7_ANALYZE_FAIL;
                }

            case MSSQL_PRELOGIN_TERMINATOR:
                break;

            default:
                i_ssl_flg = FR_YES;
                break;
        }

        /* 不符合login上下文格式 */
        if (i_ssl_flg == FR_YES)
        {
            frlist_remove_all(&st_header, __sqlserver_token_node_free);
            break;
        }
    }

    /* 不是SSL 句柄 */
    if (i_ssl_flg == FR_NO)
    {
        /* 根据token list解析数据 */
        p_st_node = FRLIST_FIRST_NODE(&st_header);
        while (p_st_node)
        {
            p_st_token = (Mssql_perlogin_token *)FRLIST_GET_NODE_DATA(p_st_node);
            uc_prelogin_token = p_st_token->uc_token_type;
            us_offset = p_st_token->us_offset;
            us_length = p_st_token->us_length;
            switch (uc_prelogin_token)
            {
                /* PL_OPTION_DATA = UL_VERSION(ULONG) US_SUBBUILD(USHORT) */
                case MSSQL_PRELOGIN_VERSION:
                    if (us_length != MSSQL_TDS_USHORT_LEN + MSSQL_TDS_ULONG_LEN
                        || us_offset + us_length > ui_buffer_len)
                    {
                        i_ssl_flg = FR_YES;
                    }
                    break;

                /* PL_OPTION_DATA = B_FENCRYPTION(BYTE) */
                /* PL_OPTION_DATA = B_MARS(BYTE) */
                /* PL_OPTION_DATA = B_FEDAUTHREQUIRED(BYTE) */
                case MSSQL_PRELOGIN_ENCRYPTION:
                case MSSQL_PRELOGIN_MARS:
                case MSSQL_PRELOGIN_FEDAUTH:
                    if (us_length != MSSQL_TDS_BYTE_LEN
                       || us_offset + us_length > ui_buffer_len)
                    {
                        i_ssl_flg = FR_YES;
                    }
                    break;

                /* PL_OPTION_DATA = *BYTE %x00 */
                case MSSQL_PRELOGIN_INSTOPT:
                    if (us_length == 0 || us_offset + us_length > ui_buffer_len)
                    {
                        i_ssl_flg = FR_YES;
                    }
                    break;

                /* PL_OPTION_DATA = UL_THREADID(ULONG) */
                case MSSQL_PRELOGIN_THREADID:
                    if (us_length != MSSQL_TDS_ULONG_LEN
                        || us_offset + us_length > ui_buffer_len)
                    {
                        i_ssl_flg = FR_YES;
                    }
                    break;

                /* PL_OPTION_DATA = GUID_CONNID(16byte) ACTIVITYID(20byte) */
                case MSSQL_PRELOGIN_TRACEID:
                    if (us_length != 16 + 20
                        || us_offset + us_length > ui_buffer_len)
                    {
                        i_ssl_flg = FR_YES;
                    }
                    break;

                /* PL_OPTION_DATA = NONCE（32byte) */
                case MSSQL_PRELOGIN_NONCEOPT:
                    if (us_length != 32
                        || us_offset + us_length > ui_buffer_len)
                    {
                        i_ssl_flg = FR_YES;
                    }
                    break;
            }

            /* 不符合login上下文格式 */
            if (i_ssl_flg == FR_YES)
            {
                break;
            }
            p_st_node = FRLIST_NEXT_NODE(p_st_node);
        }
    }

    /* 释放链表 */
    frlist_remove_all(&st_header, __sqlserver_token_node_free);
    if (i_ser_cli_flg == MSSQL_CLI2SRV)
    {
        sqlserver_destroy_request(&(p_st_private->p_st_req));
        /* 申请request */
        p_st_req = (L7_req_sqlserver *)frmalloc(sizeof(L7_req_sqlserver));
        if (p_st_req == NULL)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        memset(p_st_req, 0x0, sizeof(L7_req_sqlserver));

        /* resquest不上报，将type设置为MSSQL_NULL，对应的response也不上报 */
        p_st_req->u8_request_type = MSSQL_TDS_PRELOGIN;
        p_st_private->p_st_req = p_st_req;
    }

    //frdbg("Parse prelogin succ!\n");
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  Frdata_field释放
*  ARGS     :  pp_st_value(Frdata_field)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void sqlserver_frdata_node_free(Frlist_node *p_st_node)
{
    if( p_st_node == NULL || p_st_node->data == NULL)
    {
        return;
    }

    Frdata_field *p_st_data = (Frdata_field *)p_st_node->data;
    if (p_st_data->p_field_name)
    {
        frfree(p_st_data->p_field_name);
    }
    if (p_st_data->p_field_value)
    {
        frfree(p_st_data->p_field_value);
    }

    frfree(p_st_node->data);
    p_st_node->data = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  Frdata_field释放
*  ARGS     :  pp_st_value(Frdata_field)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void sqlserver_frdata_free(Frdata_field **pp_st_value)
{
    if (pp_st_value == NULL || *pp_st_value == NULL)
    {
        return;
    }

    Frdata_field *p_st_data = *pp_st_value;
    if (p_st_data->p_field_name)
    {
        frfree(p_st_data->p_field_name);
    }
    if (p_st_data->p_field_value)
    {
        frfree(p_st_data->p_field_value);
    }

    frfree(p_st_data);
    *pp_st_value = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  session释放
*  ARGS     :  pp_st_session(L7session_sqlserver)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void sqlserver_destroy_session(L7session_sqlserver **pp_st_session)
{
    if (pp_st_session == NULL || *pp_st_session == NULL)
    {
        return;
    }

    L7session_sqlserver *p_st_session = *pp_st_session;
    sqlserver_free((void **)&p_st_session->p_cli_host_user);
    sqlserver_free((void **)&p_st_session->p_program);
    sqlserver_free((void **)&p_st_session->p_db_name);
    sqlserver_free((void **)&p_st_session->p_db_user);
    sqlserver_free((void **)&p_st_session->p_tds_charset);
    frfree(p_st_session);
    *pp_st_session = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  大整数相乘
*  ARGS     :  p_multiplier(乘数)
*           :  p_multiplicand(被乘数)
*           :  p_result(乘积)
*  RTN      :  void
*  NOTE     :  适用与本.c文件内部调用，若需要共同出来，则需要扩张最大长度的值
*******************************************************************************/
FR_STATIC void __sqlserver_bigint_multi(const char *p_multiplier
                                      , char *p_multiplicand
                                      , char *p_result)
{
    int i_loop1 = 0;
    int i_loop2 = 0;
	int i_output_flg = FR_NO;
	unsigned int ui_multiplier_len = strlen(p_multiplier);
	unsigned int ui_p_multiplicand_len = strlen(p_multiplicand);
    unsigned arr_multiplier_trans[ui_multiplier_len + 1];
    unsigned arr_multiplicand_trans[ui_p_multiplicand_len + 1];
    unsigned arr_result[MSSQL_16BYTE_MAX_LEN + 1];
	memset(arr_multiplier_trans, 0, sizeof(arr_multiplier_trans));
	memset(arr_multiplicand_trans, 0, sizeof(arr_multiplicand_trans));
	memset(arr_result, 0, sizeof(arr_result));

    /* 乘数字符串转数字 */
	for(i_loop1 = ui_multiplier_len - 1; i_loop1 >= 0; i_loop1--)
	{
        arr_multiplier_trans[i_loop2++] = p_multiplier[i_loop1] - '0';
	}

	i_loop2 = 0;
	/* 被乘数字符串转数字 */
	for(i_loop1 = ui_p_multiplicand_len - 1; i_loop1 >= 0; i_loop1--)
	{
        arr_multiplicand_trans[i_loop2++] = p_multiplicand[i_loop1] - '0';
	}

    /* 每一轮都用乘数的一位，去和被乘数各位相乘，从乘数的个位开始 */
	for(i_loop1 = 0; i_loop1 < (int) ui_p_multiplicand_len; i_loop1++)
    {
        /* 用选定的乘数的那一位，去乘被乘数的各位 */
        for( i_loop2 = 0; i_loop2 < (int) ui_multiplier_len; i_loop2++)
        {
            arr_result[i_loop1 + i_loop2] += arr_multiplicand_trans[i_loop1] * arr_multiplier_trans[i_loop2];
        }
    }

    /* 下面的循环统一处理进位问题 */
    for(i_loop1 = 0; i_loop1 < MSSQL_16BYTE_MAX_LEN; i_loop1++)
    {
        if( arr_result[i_loop1] >= 10 )
        {
            arr_result[i_loop1 + 1] += arr_result[i_loop1] / 10;
            arr_result[i_loop1] %= 10;
        }
    }

	/* 下面输出结果 */
    for(i_loop1 = MSSQL_16BYTE_MAX_LEN; i_loop1 >= 0; i_loop1--)
    {
        if(i_output_flg == FR_YES)
        {
            snprintf(p_result, MSSQL_16BYTE_MAX_LEN + 1, "%d", arr_result[i_loop1]);
            p_result++;
        }
        else if(arr_result[i_loop1])
        {
            snprintf(p_result, MSSQL_16BYTE_MAX_LEN + 1, "%d", arr_result[i_loop1]);
            p_result++;
            i_output_flg = FR_YES;
        }
    }
    if(i_output_flg == FR_NO)
    {
        snprintf(p_result, MSSQL_16BYTE_MAX_LEN + 1, "%d", arr_result[0]);
    }
	return;
}

/*******************************************************************************
*  FUNC     :  大整数加法
*  ARGS     :  p_addend(加数)
*           :  p_augend(被加数)
*           :  p_result(和)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
FR_STATIC void __sqlserver_bigint_add(char *p_addend
                                    , char *p_augend
                                    , char *p_result)
{
    int i_loop1 = 0;
    int i_loop2 = 0;
	int i_output_flg = FR_NO;
	unsigned int ui_addend_len = strlen(p_addend);
	unsigned int ui_augend_len = strlen(p_augend);
	unsigned int ui_large_len = ui_addend_len > ui_augend_len ? ui_addend_len : ui_augend_len;
    unsigned arr_addend_trans[ui_large_len + 1];
    unsigned arr_augend_trans[ui_large_len + 1];
    unsigned arr_result[MSSQL_16BYTE_MAX_LEN + 1];
	memset(arr_addend_trans, 0, sizeof(arr_addend_trans));
	memset(arr_augend_trans, 0, sizeof(arr_augend_trans));
	memset(arr_result, 0, sizeof(arr_result));

    /* 乘数字符串转数字 */
	for(i_loop1 = ui_addend_len - 1; i_loop1 >= 0; i_loop1--)
	{
        arr_addend_trans[i_loop2++] = p_addend[i_loop1] - '0';
	}

	i_loop2 = 0;
	/* 被乘数字符串转数字 */
	for(i_loop1 = ui_augend_len - 1; i_loop1 >= 0; i_loop1--)
	{
        arr_augend_trans[i_loop2++] = p_augend[i_loop1] - '0';
	}

    /* 下面的循环统一处理进位问题 */
    for(i_loop1 = 0; i_loop1 < (int) ui_large_len; i_loop1++)
    {
        arr_result[i_loop1 + 1] += (arr_addend_trans[i_loop1] + arr_augend_trans[i_loop1])/ 10;
        arr_result[i_loop1] += (arr_addend_trans[i_loop1] + arr_augend_trans[i_loop1]) % 10;
    }

	/* 下面输出结果 */
    for(i_loop1 = MSSQL_16BYTE_MAX_LEN; i_loop1 >= 0; i_loop1--)
    {
        if(i_output_flg == FR_YES)
        {
            snprintf(p_result, MSSQL_16BYTE_MAX_LEN + 1, "%d", arr_result[i_loop1]);
            p_result++;
        }
        else if(arr_result[i_loop1])
        {
            snprintf(p_result, MSSQL_16BYTE_MAX_LEN + 1, "%d", arr_result[i_loop1]);
            p_result++;
            i_output_flg = FR_YES;
        }
    }

    if(i_output_flg == FR_NO)
    {
        snprintf(p_result, MSSQL_16BYTE_MAX_LEN + 1, "%d", arr_result[i_loop1]);
    }
	return;
}


/*******************************************************************************
*  FUNC     :  取得byte数据
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  i_byte_flg(B_VARBYTE/US_VARBYTE/L_VARBYTE)
*           :  pp_out_bytes(出力实际长度)
*           :  p_ui_out_len(出力数据长度)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_get_varbytes(Frbyte_Packet *p_st_data
                           , int i_whole_flg
                           , int i_byte_flg
                           , int i_get_value_flg
                           , char **pp_out_bytes
                           , unsigned int *p_ui_out_len)
{
    int i_ret = FR_SUCC;
    uint8_t u8_bytes_len = 0;
    uint16_t u16_bytes_len = 0;
    uint32_t u32_bytes_len = 0;
    unsigned int ui_bytes_len = 0;
    char *p_output = NULL;

    switch (i_byte_flg)
    {
        case APM_TDS_B_VARBYTE:
            /* B_VARBYTE = BYTELEN *BYTE */
            if (bytebuff_remaining(p_st_data) < 1)
            {
                 goto error;
            }
            /* 取得长度位,并跳过 */
            bytebuff_get_char(p_st_data, &u8_bytes_len);
            ui_bytes_len = u8_bytes_len;
            break;

        case APM_TDS_US_VARBYTE:
            /* US_VARBYTE = USHORTLEN *BYTE */
            if (bytebuff_remaining(p_st_data) < 2)
            {
                goto error;
            }
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_bytes_len
                                      , BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_bytes_len = u16_bytes_len;
            break;

        case APM_TDS_L_VARBYTE:
            /* L_VARBYTE = LONGLEN *BYTE */
            if (bytebuff_remaining(p_st_data) < 4)
            {
                goto error;
            }
            i_ret = bytebuff_get_int(p_st_data, 4, &u32_bytes_len
                                     , BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_bytes_len = u32_bytes_len;
            break;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    /* 长度不足 */
    if (ui_bytes_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        goto error;
    }

    /* 长度为0时，出力为NULL */
    if (ui_bytes_len != 0 && i_get_value_flg == FR_YES)
    {
        /* 申请内存用于存放出力数据 */
        p_output = (char *)frmalloc(ui_bytes_len + 1);
        if (p_output == NULL)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        i_ret = bytebuff_get_bytes(p_st_data, p_output, ui_bytes_len);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else
    {
        bytebuff_skip(p_st_data, ui_bytes_len);
    }

    /* 设置出力信息 */
    *pp_out_bytes = p_output;
    *p_ui_out_len = ui_bytes_len;
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  取得varchar数据
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  i_char_flg(B_VARCHAR/US_VARCHAR)
*           :  i_get_value_flg(是否需要取出具体值)
*           :  pp_out_bytes(出力实际长度)
*           :  p_ui_out_len(出力数据长度)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_get_varchar(Frbyte_Packet *p_st_data
                         , int i_whole_flg
                         , int i_char_flg
                         , int i_get_value_flg
                         , char **pp_out_char
                         , unsigned int *p_ui_out_len)
{
    int i_ret = FR_SUCC;
    uint8_t u8_bytes_len = 0;
    uint16_t u16_bytes_len = 0;
    unsigned int ui_bytes_len = 0;
    char *p_buff = NULL;

    switch (i_char_flg)
    {
        case APM_TDS_B_VARCHAR:
            /* B_VARBYTE = BYTELEN *BYTE */
            if (bytebuff_remaining(p_st_data) < 1)
            {
                 goto error;
            }
            /* 取得长度位,并跳过 */
            bytebuff_get_char(p_st_data, &u8_bytes_len);
            ui_bytes_len = u8_bytes_len * 2;
            break;

        case APM_TDS_US_VARCHAR:
            /* US_VARBYTE = USHORTLEN *BYTE */
            if (bytebuff_remaining(p_st_data) < 2)
            {
                goto error;
            }
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_bytes_len
                                      , BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_bytes_len = u16_bytes_len * 2;
            break;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    /* 长度不足 */
    if (ui_bytes_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        goto error;
    }

    /* 长度为0时，出力为NULL */
    if (ui_bytes_len != 0 && i_get_value_flg == FR_YES)
    {
        p_buff = (char *)frmalloc(ui_bytes_len);
        if (p_buff == NULL)
        {
            return APM_L7_ANALYZE_FAIL;
        }

        i_ret = bytebuff_get_bytes(p_st_data, p_buff, ui_bytes_len);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }

        i_ret = iconv_to_utf8(p_buff, ui_bytes_len, APM_CHARSET_UCS2, pp_out_char, p_ui_out_len);
        frfree(p_buff);
        if (i_ret == 2)
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else
    {
        bytebuff_skip(p_st_data, ui_bytes_len);
    }

    /* 设置出力信息 */
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析LOGIN数据
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  i_endian_type(网络字节序标志(0表示需要转换，1表示不需要))
*           :  p_us_size(出力实际长度)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __sqlserver_int_pow(unsigned long long ull_x
                               , unsigned long long ull_y
                               , unsigned long long *p_ull_result)
{
    unsigned long long ull_result = 0;
    if (ull_x == 0)
    {
        *p_ull_result = 0;
        return FR_SUCC;
    }

    if (ull_y == 0)
    {
        *p_ull_result = 1;
        return FR_SUCC;
    }

    ull_result = ull_x;
    while (--ull_y)
    {
        /* 防止越界 */
        if (ULLONG_MAX/ull_x < ull_result && ull_y != 0)
        {
            return FR_FAIL;
        }

        ull_result = ull_result * ull_x;
    }

    *p_ull_result = ull_result;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得TDS版本号
*  ARGS     :  p_st_data(入力数据)
*           :  i_cli_srv_flg(客户端OR服务端
*           :  p_i_ver(TDS版本)
*  RTN      :  FR_SUCC       (normal)
*              FR_FAIL       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_tds_ver_get(Frbyte_Packet *p_st_data
                          , int i_cli_srv_flg
                          , int *p_i_ver)
{
    int i_ret = FR_SUCC;
    char arr_ver[4] = {0};

    /* 取得version字段 */
    i_ret = bytebuff_get_bytes(p_st_data, arr_ver, MSSQL_TDS_DWORD_LEN);
    if (i_ret != FR_SUCC)
    {
        return FR_FAIL;
    }

    /* 客户端版本号判定 */
    if (i_cli_srv_flg == MSSQL_CLI2SRV)
    {
        /* TDS Version */
        if (memcmp(arr_ver, "\x00\x00\x00\x70", MSSQL_TDS_DWORD_LEN) == 0)
        {
            *p_i_ver = MSSQL_TDS_VER_70;
        }
        else if (memcmp(arr_ver, "\x00\x00\x00\x71", MSSQL_TDS_DWORD_LEN) == 0)
        {
            *p_i_ver = MSSQL_TDS_VER_71;
        }
        else if (memcmp(arr_ver, "\x01\x00\x00\x71", MSSQL_TDS_DWORD_LEN) == 0)
        {
            *p_i_ver = MSSQL_TDS_VER_71R1;
        }
        else if (memcmp(arr_ver, "\x02\x00\x09\x72", MSSQL_TDS_DWORD_LEN) == 0)
        {
            *p_i_ver = MSSQL_TDS_VER_72;
        }
        else if (memcmp(arr_ver, "\x03\x00\x0A\x73", MSSQL_TDS_DWORD_LEN) == 0)
        {
            *p_i_ver = MSSQL_TDS_VER_73A;
        }
        else if (memcmp(arr_ver, "\x03\x00\x0B\x73", MSSQL_TDS_DWORD_LEN) == 0)
        {
            *p_i_ver = MSSQL_TDS_VER_73B;
        }
        else if (memcmp(arr_ver, "\x04\x00\x00\x74", MSSQL_TDS_DWORD_LEN) == 0)
        {
            *p_i_ver = MSSQL_TDS_VER_74;
        }
        else
        {
            return FR_FAIL;
        }
    }
    /* 服务端端版本号判定 */
    else
    {
        /* TDS Version */
        if (memcmp(arr_ver, "\x07\x00\x00\x00", MSSQL_TDS_DWORD_LEN) == 0)
        {
            *p_i_ver = MSSQL_TDS_VER_70;
        }
        else if (memcmp(arr_ver, "\x07\x01\x00\x00", MSSQL_TDS_DWORD_LEN) == 0)
        {
            *p_i_ver = MSSQL_TDS_VER_71;
        }
        else if (memcmp(arr_ver, "\x71\x00\x00\x01", MSSQL_TDS_DWORD_LEN) == 0)
        {
            *p_i_ver = MSSQL_TDS_VER_71R1;
        }
        else if (memcmp(arr_ver, "\x72\x09\x00\x02", MSSQL_TDS_DWORD_LEN) == 0)
        {
            *p_i_ver = MSSQL_TDS_VER_72;
        }
        else if (memcmp(arr_ver, "\x73\x0A\x00\x03", MSSQL_TDS_DWORD_LEN) == 0)
        {
            *p_i_ver = MSSQL_TDS_VER_73A;
        }
        else if (memcmp(arr_ver, "\x73\x0B\x00\x03", MSSQL_TDS_DWORD_LEN) == 0)
        {
            *p_i_ver = MSSQL_TDS_VER_73B;
        }
        else if (memcmp(arr_ver, "\x74\x00\x00\x04", MSSQL_TDS_DWORD_LEN) == 0)
        {
            *p_i_ver = MSSQL_TDS_VER_74;
        }
        else
        {
            return FR_FAIL;
        }
    }

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析TYPE_INFO
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  i_rpc_or_colmeta(当前typeinfo是属于RPC的还是COLMETADATA的)
*           :  p_i_min_tds_ver(在未知版本的情况取得较为可信的版本)
*           :  p_u8_data_type(返回数据类型)
*           :  p_ui_precision(precision)
*           :  p_ui_scale(scale)
*           :  p_i_partlentype(当前data type是否属于PLP)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_type_info_parse(Frbyte_Packet *p_st_data
                              , int i_whole_flg
                              , int i_rpc_or_colmeta
                              , int *p_i_min_tds_ver
                              , uint8_t *p_u8_data_type
                              , uint8_t *p_u8_precision
                              , uint8_t *p_u8_scale
                              , int *p_i_partlentype)
{
    int i_ret = 0;
    uint16_t u16_max_len = 0;
    uint8_t u8_len_tmp = 0;
    uint16_t u16_len_tmp = 0;
    unsigned int ui_len_tmp = 0;
    *p_i_partlentype = FR_NO;                   /* 默认情况不是PLP类型 */

    /* TYPE_INFO的定义
    *      TYPE_INFO = FIXEDLENTYPE
                     / (VARLENTYPE TYPE_VARLEN [COLLATION])
                     / (VARLENTYPE TYPE_VARLEN [PRECISION SCALE])
                     / (VARLENTYPE SCALE) ; (introduced in TDS 7.3)
                     / VARLENTYPE ; (introduced in TDS 7.3)
                     / (PARTLENTYPE [USHORTMAXLEN] [COLLATION] [XML_INFO] [UDT_INFO])
    */

    /* TYPE_VARLEN说明
    * 如果data type是SSVARIANTTYPE,TEXTTYPE,NTEXTTYPE,IMAGETYPE时TYPE_VARLEN是LONGLEN(4byte),
    * 如果data type是BIGCHARTYPE,BIGVARCHARTYPE,NCHARTYPE, NVARCHARTYPE, BIGBINARYTYPE,BIGVARBINARYTYP
    * 时TYPE_VARLEN是USHORTLEN(2byte),其他的类型TYPE_VARLEN都是BYTELEN(1byte)
    */

    /* 其他说明
    *  COLLATION(5byte),PRECISION(1byte),SCALE(1byte),USHORTMAXLEN(0xFFFF)
    * XML_INFO = SCHEMA_PRESENT [DBNAME OWNING_SCHEMA XML_SCHEMA_COLLECTION]
    * SCHEMA_PRESENT(1byte)为0x01时才有后面内容，0x00没有
    */

    /* 跳过TDS数据类型表示位 */
    if (bytebuff_remaining(p_st_data) < 1)
    {
        if (i_whole_flg == FR_YES)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        else
        {
            return APM_L7_ANALYZE_TODO;
        }
    }
    /* 取得数据类型 */
    bytebuff_get_char(p_st_data, p_u8_data_type);

    /* 根据TDS数据类型解析type info */
    switch(*p_u8_data_type)
    {
        /* FIXEDLENTYPE */
        case TDS_DATA_TYPE_NULL:     /* Null (no data associated with this type) */
        case TDS_DATA_TYPE_INT1:     /* TinyInt (1 byte data representation) */
        case TDS_DATA_TYPE_BIT:      /* Bit (1 byte data representation) */
        case TDS_DATA_TYPE_INT2:     /* SmallInt (2 byte data representation) */
        case TDS_DATA_TYPE_INT4:     /* Int (4 byte data representation) */
        case TDS_DATA_TYPE_FLT4:     /* Real (4 byte data representation) */
        case TDS_DATA_TYPE_DATETIM4: /* SmallDateTime (4 byte data representation) */
        case TDS_DATA_TYPE_MONEY4:   /* SmallMoney (4 byte data representation) */
        case TDS_DATA_TYPE_INT8:     /* BigInt (8 byte data representation) */
        case TDS_DATA_TYPE_FLT8:     /* Float (8 byte data representation) */
        case TDS_DATA_TYPE_MONEY:    /* Money (8 byte data representation) */
        case TDS_DATA_TYPE_DATETIME: /* DateTime (8 byte data representation) */
            break;

        /*
        * DATE MUST NOT have a TYPE_VARLEN.
        * The value is either 3 bytes or 0 bytes (null)
        */
        case TDS_DATA_TYPE_DATEN:           /* (introduced in TDS 7.3) */
            /* 设置TDS版本 */
            if (*p_i_min_tds_ver < MSSQL_TDS_VER_73A)
            {
                *p_i_min_tds_ver = MSSQL_TDS_VER_73A;
            }
            break;

        /* VARLENTYPE SCALE
        * TIME, DATETIME2, and DATETIMEOFFSET MUST NOT have a TYPE_VARLEN, and
        * SCALE (without PRECISION) MUST occur if the type is TIME,
        * DATETIME2 or DATETIMEOFFSET
        */
        case TDS_DATA_TYPE_TIMEN:           /* (introduced in TDS 7.3) */
        case TDS_DATA_TYPE_DATETIME2N:      /* (introduced in TDS 7.3) */
        case TDS_DATA_TYPE_DATETIMEOFFSETN: /* (introduced in TDS 7.3) */
            /* 设置TDS版本 */
            if (*p_i_min_tds_ver < MSSQL_TDS_VER_73A)
            {
                *p_i_min_tds_ver = MSSQL_TDS_VER_73A;
            }
            /* 1 is length of SCALE */
            if (bytebuff_remaining(p_st_data) < 1)
            {
                goto error;
            }
            bytebuff_get_char(p_st_data, p_u8_scale);
            break;

        /* VARLENTYPE TYPE_VARLEN PRECISION SCALE */
        /*
        * PRECISION and SCALE MUST occur if the type is NUMERIC,
        * NUMERICN, DECIMAL or DECIMALN
        */
        case TDS_DATA_TYPE_NUMERIC:
        case TDS_DATA_TYPE_NUMERICN:
        case TDS_DATA_TYPE_DECIMALN:
        case TDS_DATA_TYPE_DECIMAL:
            /* TYPE_VARLEN PRECISION SCALE */
            if (bytebuff_remaining(p_st_data) < 1 + 1 + 1)
            {
                goto error;
            }
            bytebuff_skip(p_st_data, 1);
            bytebuff_get_char(p_st_data, p_u8_precision);
            bytebuff_get_char(p_st_data, p_u8_scale);
            break;

        /*
        * VARLENTYPE TYPE_VARLEN COLLATION
        * COLLATION occurs only if the type is BIGCHARTYPE, BIGVARCHRTYPE,
        * TEXTTYPE,NTEXTTYPE, NCHARTYPE or NVARCHARTYPE.
        */
        case TDS_DATA_TYPE_TEXT:
        case TDS_DATA_TYPE_NTEXT:
            /* TYPE_VARLEN COLLATION */
            if (bytebuff_remaining(p_st_data) < 4 + 5)
            {
                goto error;
            }
            /* with COLLATION(5byte) */
            bytebuff_skip(p_st_data, 4 + 5);
            break;

        /* VARLENTYPE TYPE_VARLEN COLLATION
        * COLLATION occurs only if the type is BIGCHARTYPE, BIGVARCHRTYPE,
        * TEXTTYPE,NTEXTTYPE, NCHARTYPE or NVARCHARTYPE.
        */
        case TDS_DATA_TYPE_BIGCHAR:
        case TDS_DATA_TYPE_BIGVARCHR:
        case TDS_DATA_TYPE_NCHAR:
        case TDS_DATA_TYPE_NVARCHAR:
            /* TYPE_VARLEN COLLATION */
            if (bytebuff_remaining(p_st_data) < 2 + 5)
            {
                goto error;
            }
            /* get length */
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_max_len
                                       , BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /*
            * BIGVARCHR and BIGVARBIN and NVARCHAR with unlimited max
            * size(0xFFFF), defined by PARTLENTYPE(introduced in TDS 7.2)
            */
            if (u16_max_len == 0xFFFF
                && (*p_u8_data_type == TDS_DATA_TYPE_BIGVARCHR
                    ||  *p_u8_data_type == TDS_DATA_TYPE_NVARCHAR))
            {
                /* 设置TDS版本 */
                if (*p_i_min_tds_ver < MSSQL_TDS_VER_72)
                {
                    *p_i_min_tds_ver = MSSQL_TDS_VER_72;
                }
                *p_i_partlentype = FR_YES;
            }
            /* with COLLATION(5byte) */
            bytebuff_skip(p_st_data, 5);
            break;

        /* UDT_INFO always occurs if the type is UDTTYPE */
        case TDS_DATA_TYPE_UDT:            /* CLR-UDT (introduced in TDS 7.2) */
            /* 设置TDS版本 */
            if (*p_i_min_tds_ver < MSSQL_TDS_VER_72)
            {
                *p_i_min_tds_ver = MSSQL_TDS_VER_72;
            }
            *p_i_partlentype = FR_YES;

            /* 解析UDT_INFO */
            /* 当是COLMETADATA时，有MAX_BYTE_SIZE,跳过两位的MAX_BYTE_SIZE */
            if (i_rpc_or_colmeta == MSSQL_COLMETA)
            {
                if (bytebuff_remaining(p_st_data) <= 2)
                {
                    goto error;
                }
                bytebuff_skip(p_st_data, 2);
            }
            else if (bytebuff_remaining(p_st_data) == 0)
            {
                goto error;
            }

            /* 1 is DBNAME length */
            bytebuff_get_char(p_st_data, &u8_len_tmp);
            /* DBNAME = B_VARCHAR */
            ui_len_tmp = u8_len_tmp * 2;
            if (ui_len_tmp >= (unsigned int)bytebuff_remaining(p_st_data))
            {
                goto error;
            }
            /* skip DBNAME */
            bytebuff_skip(p_st_data, ui_len_tmp);

            /* 1 is SCHEMA_NAME length */
            bytebuff_get_char(p_st_data, &u8_len_tmp);
            /* SCHEMA_NAME = B_VARCHAR */
            ui_len_tmp = u8_len_tmp * 2;
            if (ui_len_tmp >= (unsigned int)bytebuff_remaining(p_st_data))
            {
                goto error;
            }
            /* skip SCHEMA_NAME */
            bytebuff_skip(p_st_data, ui_len_tmp);

            /* 1 is TYPE_NAME length */
            bytebuff_get_char(p_st_data, &u8_len_tmp);
            /* TYPE_NAME = B_VARCHAR */
            ui_len_tmp = u8_len_tmp * 2;
            if (ui_len_tmp >= (unsigned int)bytebuff_remaining(p_st_data))
            {
                goto error;
            }
            /* skip TYPE_NAME */
            bytebuff_skip(p_st_data, ui_len_tmp);

            /* 当是COLMETADATA时，有UDT_METADATA，跳过两位的UDT_METADATA */
            if (i_rpc_or_colmeta == MSSQL_COLMETA)
            {
                /* 2 is SCHEMA_NAME length */
                if (bytebuff_remaining(p_st_data) < 2)
                {
                    goto error;
                }
                /* get length */
                i_ret = bytebuff_get_short(p_st_data, 2, &u16_len_tmp
                                           , BYTE_LITTLE_ENDIAN);
                if (i_ret != FR_SUCC)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                /* UDT_METADATA = US_VARCHAR */
                ui_len_tmp = u16_len_tmp * 2;
                if (ui_len_tmp > (unsigned int)bytebuff_remaining(p_st_data))
                {
                    goto error;
                }
                /* skip UDT_METADATA */
                bytebuff_skip(p_st_data, ui_len_tmp);
            }
            break;

        /* XML_INFO always occurs if the type is XMLTYPE */
        case TDS_DATA_TYPE_XML:             /* XML (introduced in TDS 7.2) */
            /* 设置TDS版本 */
            if (*p_i_min_tds_ver < MSSQL_TDS_VER_72)
            {
                *p_i_min_tds_ver = MSSQL_TDS_VER_72;
            }
            *p_i_partlentype = FR_YES;
            /*
            * SCHEMA_PRESENT specifies "0x01" if the type has an associated
            * schema collection and DBNAME, OWNING_SCHEMA and
            * XML_SCHEMA_COLLECTION MUST be included in the stream,
            * or '0x00' otherwise
            */
            if (bytebuff_remaining(p_st_data))
            {
                /* get SCHEMA_PRESENT */
                bytebuff_get_char(p_st_data, &u8_len_tmp);
                if (u8_len_tmp == 0x01)
                {
                    if (bytebuff_remaining(p_st_data))
                    {
                        /* get DBNAME length */
                        bytebuff_get_char(p_st_data, &u8_len_tmp);
                        /* DBNAME = B_VARCHAR */
                        ui_len_tmp = u8_len_tmp * 2;
                        if (ui_len_tmp >= (unsigned int)bytebuff_remaining(p_st_data))
                        {
                            goto error;
                        }
                        /* skip DBNAME */
                        bytebuff_skip(p_st_data, ui_len_tmp);

                        /* get OWNING_SCHEMA length */
                        bytebuff_get_char(p_st_data, &u8_len_tmp);
                        /* OWNING_SCHEMA = B_VARCHAR */
                        ui_len_tmp = u8_len_tmp * 2;
                        if (ui_len_tmp > (unsigned int)bytebuff_remaining(p_st_data))
                        {
                            goto error;
                        }
                        /* skip OWNING_SCHEMA */
                        bytebuff_skip(p_st_data, ui_len_tmp);

                        /* 2 is XML_SCHEMA_COLLECTION length */
                        if (bytebuff_remaining(p_st_data) < 2)
                        {
                            goto error;
                        }
                        /* get length */
                        i_ret = bytebuff_get_short(p_st_data
                                                  , MSSQL_TDS_USHORT_LEN
                                                  , &u16_len_tmp
                                                  , BYTE_LITTLE_ENDIAN);
                        if (i_ret != FR_SUCC)
                        {
                            return APM_L7_ANALYZE_FAIL;
                        }
                        /* XML_SCHEMA_COLLECTION = US_VARCHAR */
                        ui_len_tmp = u16_len_tmp * 2;
                        if (ui_len_tmp > (unsigned int)bytebuff_remaining(p_st_data))
                        {
                            goto error;
                        }
                        /* skip OWNING_SCHEMA */
                        bytebuff_skip(p_st_data, ui_len_tmp);
                    }
                    else
                    {
                        goto error;
                    }
                }
                else if (u8_len_tmp != 0x00)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
            }
            else
            {
                goto error;
            }
            break;

        /* BYTELEN_TYPE */
        case TDS_DATA_TYPE_GUID:            /* UniqueIdentifier */
        case TDS_DATA_TYPE_INTN:
        case TDS_DATA_TYPE_BITN:
        case TDS_DATA_TYPE_FLTN:
        case TDS_DATA_TYPE_MONEYN:
        case TDS_DATA_TYPE_DATETIMN:
        case TDS_DATA_TYPE_CHAR:            /* Char (legacy support) */
        case TDS_DATA_TYPE_VARCHAR:         /* VarChar (legacy support) */
        case TDS_DATA_TYPE_BINARY:          /* Binary (legacy support) */
        case TDS_DATA_TYPE_VARBINARY:       /* VarBinary (legacy support) */
            if (bytebuff_remaining(p_st_data))
            {
                bytebuff_skip(p_st_data, 1);
            }
            else
            {
                goto error;
            }
            break;

        /* USHORTLEN_TYPE */
        case TDS_DATA_TYPE_BIGBINARY:       /* Binary */
            if (bytebuff_remaining(p_st_data) < 2)
            {
                goto error;
            }
            else
            {
                bytebuff_skip(p_st_data, 2);
            }
            break;

        /* USHORTLEN_TYPE */
        case TDS_DATA_TYPE_BIGVARBIN:       /* VarBinary */
            if (bytebuff_remaining(p_st_data) < 2)
            {
                goto error;
            }
            /* get length */
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_max_len
                                       , BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* TDS版本设定 */
            if (u16_max_len == 0xFFFF)
            {
                *p_i_partlentype = FR_YES;
                if (*p_i_min_tds_ver < MSSQL_TDS_VER_72)
                {
                    *p_i_min_tds_ver = MSSQL_TDS_VER_72;
                }
            }
            break;

        /* LONGLEN_TYPE */
        case TDS_DATA_TYPE_IMAGE:           /* Image */
            if (bytebuff_remaining(p_st_data) < 4)
            {
                goto error;
            }
            else
            {
                bytebuff_skip(p_st_data, 4);
            }
            break;

        case TDS_DATA_TYPE_SSVARIANT:  /* Sql_Variant (introduced in TDS 7.2) */
            if (bytebuff_remaining(p_st_data) < 4)
            {
                goto error;
            }
            else
            {
                bytebuff_skip(p_st_data, 4);
            }
            /* 设置TDS版本 */
            if (*p_i_min_tds_ver < MSSQL_TDS_VER_72)
            {
                //*p_i_min_tds_ver = MSSQL_TDS_VER_72;
            }
            break;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  跳过固定长度位
*  ARGS     :  p_st_data(入力bytebuff)
*           :  i_whole_flg(数据包是否已经接收完成)
*           :  i_endian(字节序)
*           :  ui_var_len(要跳过的长度位长度)
*  RTN      :  APM_L7_ANALYZE_SUCC(succ)
*              APM_L7_ANALYZE_TODO(need more data)
*              APM_L7_ANALYZE_FAIl(error)
*  NOTE     :  p_st_data肯定不为NULL
*******************************************************************************/
int sqlserver_skip_var_len(Frbyte_Packet *p_st_data
                          , int i_whole_flg
                          , LITTLE_BIG_ENDIAN i_endian
                          , unsigned int ui_var_len)
{
    int i_ret = 0;
    uint8_t u8_len = 0;
    uint16_t u16_len = 0;
    uint32_t u32_len = 0;
    unsigned int ui_len = 0;

    /* 数据长度不足 */
    if (ui_var_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        /* 还有本次请求未接收完了的数据 */
        if (i_whole_flg == FR_NO)
        {
            return APM_L7_ANALYZE_TODO;
        }
        else
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }

    switch (ui_var_len)
    {
        case 1:
            i_ret = bytebuff_get_char(p_st_data, &u8_len);
            ui_len = u8_len;
            break;

        case 2:
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, i_endian);
            ui_len = (u16_len == 0xffff) ? 0 : u16_len;
            break;

        case 4:
            i_ret = bytebuff_get_int(p_st_data, 4, &u32_len, i_endian);
            ui_len = (u32_len == 0xffffffff) ? 0 : u32_len;
            break;

        default:
            return APM_L7_ANALYZE_FAIL;

    }

    /* 数据长度不足 */
    if (ui_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        /* 还有本次请求未接收完了的数据 */
        if (i_whole_flg == FR_NO)
        {
            bytebuff_set_skip(p_st_data, ui_len - bytebuff_remaining(p_st_data));
            return APM_L7_ANALYZE_TODO;
        }
        else
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }

    /* skip length */
    i_ret = bytebuff_skip(p_st_data, ui_len);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  把数据转成UTF8字符串
*  ARGS     :  pp_inbuffer(入力buffer)
*           :  i_whole_flg(完整flag)
*           :  p_charset(charset)
*           :  u8_data_type(TDS数据类型)
*           :  pp_st_value(出力数据)
*  RTN      :  APM_L7_ANALYZE_SUCC(succ)
*              APM_L7_ANALYZE_TODO(need more data)
*              APM_L7_ANALYZE_FAIl(error)
*  NOTE     :
*******************************************************************************/
int sqlserver_get_utf8str(Frbyte_Packet *p_st_data
                          , int i_whole_flg
                          , char *p_charset
                          , uint8_t u8_data_type
                          , Frdata_field **pp_st_value)
{
    int i_ret = FR_SUCC;
    int i_null_flg = FR_NO;
    uint8_t u8_binary_value = 0;
    uint16_t u16_binary_value = 0;
    uint32_t u32_binary_value = 0;
    unsigned int ui_data_len = 0;
    char *p_binary = NULL;
    char *p_utf8_str = NULL;
    Frdata_field *p_st_value = NULL;
    unsigned int ui_uft8_len = 0;

    /* 所能处理的数据类型(CHAR/VARCHAR/NCHAR/NVARCHAR/NTEXT) */
    switch (u8_data_type)
    {
        case TDS_DATA_TYPE_CHAR:
        case TDS_DATA_TYPE_VARCHAR:
            /* 1BYTE的TYPE_VARLEN */
            if (bytebuff_remaining(p_st_data) < 1)
            {
                goto error;
            }
            /* 取得长度位,并跳过 */
            bytebuff_get_char(p_st_data, &u8_binary_value);
            ui_data_len = u8_binary_value;
            break;

        case TDS_DATA_TYPE_NCHAR:
        case TDS_DATA_TYPE_NVARCHAR:
        case TDS_DATA_TYPE_BIGVARCHR:
        case TDS_DATA_TYPE_BIGCHAR:
            /* 2BYTE的TYPE_VARLEN */
            if (bytebuff_remaining(p_st_data) < 2)
            {
                goto error;
            }
            /* 取得长度位，并跳过 */
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_binary_value
                                       , BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_data_len = u16_binary_value;
            break;

        case TDS_DATA_TYPE_TEXT:
        case TDS_DATA_TYPE_NTEXT:
            /* 4BYTE的TYPE_VARLEN */
            if (bytebuff_remaining(p_st_data) < 4)
            {
                goto error;
            }
            /* 取得长度位，并跳过 */
            i_ret = bytebuff_get_int(p_st_data, 4, &u32_binary_value
                                    , BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_data_len = u32_binary_value;
            break;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    /*
    * The 2-byte CHARBIN_NULL rule is used for BIGCHARTYPE, BIGVARCHARTYPE,
    * NCHARTYPE, NVARCHARTYPE, BIGBINARYTYPE and BIGVARBINARYTYPE types, and the
    * 4-byte CHARBIN_NULL rule is used for TEXTTYPE, NTEXTTYPE and IMAGETYPE
    */
    if (u16_binary_value == 0xFFFF || u32_binary_value == 0xFFFFFFFF)
    {
        i_null_flg = FR_YES;
        ui_data_len = 0;
    }

    /* 格式判断 */
    if (ui_data_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        goto error;
    }

    /* 申请出力结构体内存 */
    p_st_value = (Frdata_field *)frmalloc(sizeof(Frdata_field));
    if (p_st_value == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    memset(p_st_value, 0x0, sizeof(Frdata_field));
    p_st_value->em_data_type = FRSTRING;

    /* 当长度是0xFFFF时,值为空 */
    if (i_null_flg == FR_YES)
    {
        p_st_value->p_field_value = NULL;
    }
    else
    {
        p_binary = (char *)frmalloc(ui_data_len + 1);
        if (p_binary == NULL)
        {
            frfree(p_st_value);
            return APM_L7_ANALYZE_FAIL;
        }
        /* 取出buffer */
        i_ret = bytebuff_get_bytes(p_st_data, p_binary, ui_data_len);
        if (i_ret != FR_SUCC)
        {
            frfree(p_binary);
            frfree(p_st_value);
            return APM_L7_ANALYZE_FAIL;
        }
        p_binary[ui_data_len] = '\0';

        /* nchar/nvarchar/ntext是Unicode编码处理过的 */
        if (u8_data_type == TDS_DATA_TYPE_NCHAR
            || u8_data_type == TDS_DATA_TYPE_NVARCHAR
            || u8_data_type == TDS_DATA_TYPE_NTEXT)
        {
            /* 取得UTF8内容 "UNICODE" */
            i_ret = iconv_to_utf8(p_binary, ui_data_len, "UNICODE"
                                 , &p_utf8_str, &ui_uft8_len);
            frfree(p_binary);
            if (i_ret == 2)
            {
                frfree(p_st_value);
                return APM_L7_ANALYZE_FAIL;
            }
        }
        /* EBDDIC编码 */
        else if (p_charset && strncasecmp(p_charset, "CP500", 5) == 0)
        {
            /* 取得UTF8内容 "EBDDIC" */
            i_ret = iconv_to_utf8(p_binary, ui_data_len, "CP500"
                                 , &p_utf8_str, &ui_uft8_len);
            frfree(p_binary);
            if (i_ret == 2)
            {
                frfree(p_st_value);
                return APM_L7_ANALYZE_FAIL;
            }
        }
        /* 其他都是未做过Unicode编码处理的,直接取值 */
        else
        {
            p_utf8_str = p_binary;
        }
        p_st_value->p_field_value = p_utf8_str;
    }

    *pp_st_value = p_st_value;
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  取得binary数据
*  ARGS     :  pp_inbuffer(入力buffer)
*           :  p_ui_buffer_len(入力buffer的长度)
*           :  u8_data_type(TDS数据类型)
*           :  pp_st_value(出力数据)
*  RTN      :  APM_L7_ANALYZE_SUCC(succ)
*              APM_L7_ANALYZE_TODO(need more data)
*              APM_L7_ANALYZE_FAIl(error)
*  NOTE     :
*******************************************************************************/
int sqlserver_get_binary(Frbyte_Packet *p_st_data
                         , int i_whole_flg
                         , uint8_t u8_data_type
                         , Frdata_field **pp_st_value)
{
    int i_ret = 0;
    int i_null_flg = FR_NO;
    uint8_t u8_binary_value = 0;
    uint16_t u16_binary_value = 0;
    uint32_t u32_binary_value = 0;
    unsigned int ui_data_len = 0;
    unsigned int ui_skip_len = 0;
    char *p_binary = NULL;
    Frdata_field *p_st_value = NULL;

    /* 所能处理的数据类型(INTN/VARCHAR/NCHAR/NVARCHAR/IMAGE) */
    switch (u8_data_type)
    {
        case TDS_DATA_TYPE_BINARY:
        case TDS_DATA_TYPE_VARBINARY:
            /* 1BYTE的TYPE_VARLEN */
            if (bytebuff_remaining(p_st_data) < 1)
            {
                goto error;
            }
            /* 取得长度位,并跳过 */
            bytebuff_get_char(p_st_data, &u8_binary_value);
            ui_data_len = u8_binary_value;
            break;

        case TDS_DATA_TYPE_BIGVARBIN:
        case TDS_DATA_TYPE_BIGBINARY:
            /* 2BYTE的TYPE_VARLEN */
            if (bytebuff_remaining(p_st_data) < 2)
            {
                goto error;
            }
            /* 取得长度位，并跳过 */
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_binary_value
                                       , BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_data_len = u16_binary_value;
            break;

        case TDS_DATA_TYPE_SSVARIANT://todo
        case TDS_DATA_TYPE_IMAGE:
            /* 4BYTE的TYPE_VARLEN */
            if (bytebuff_remaining(p_st_data) < 4)
            {
                goto error;
            }
            /* 取得长度位，并跳过 */
            i_ret = bytebuff_get_int(p_st_data, 4, &u32_binary_value
                                    , BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_data_len = u32_binary_value;
            break;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    /*
    * The 2-byte CHARBIN_NULL rule is used for BIGCHARTYPE, BIGVARCHARTYPE,
    * NCHARTYPE, NVARCHARTYPE, BIGBINARYTYPE and BIGVARBINARYTYPE types, and the
    * 4-byte CHARBIN_NULL rule is used for TEXTTYPE, NTEXTTYPE, and IMAGETYPE
    */
    if (u16_binary_value == 0xFFFF || u32_binary_value == 0xFFFFFFFF)
    {
        i_null_flg = FR_YES;
        ui_data_len = 0;
    }

    /* 格式判断 */
    if (ui_data_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        ui_skip_len = ui_data_len - bytebuff_remaining(p_st_data);
        /* binary类型的全部不取具体值 */
        bytebuff_set_skip(p_st_data, ui_skip_len);
        goto error;
    }

    /* 申请出力结构体内存 */
    p_st_value = (Frdata_field *)frmalloc(sizeof(Frdata_field));
    if (p_st_value == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    memset(p_st_value, 0x0, sizeof(Frdata_field));
    p_st_value->em_data_type = FRBLOB;
    /* 数据为空 */
    if (i_null_flg == FR_YES)
    {
        /* 数据为空,注意此时为了设置NULL，设置类型为(char *) */
        p_st_value->p_field_value = NULL;
    }
    else
    {
        /* binary类型的全部不取具体值 */
        p_binary = frstrdup(MSSQL_BLOB_DATA);
        p_st_value->p_field_value = p_binary;
        bytebuff_skip(p_st_data, ui_data_len);
    }

    /* 出力设置 */
    *pp_st_value = p_st_value;
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  把DateTime的数据转成字符串
*  ARGS     :  pp_inbuffer(入力buffer)
*           :  p_ui_buffer_len(入力buffer的长度)
*           :  u8_data_type(数据类型)
*           :  i_get_value_flg(是否需要取得数据)
*           :  pp_st_value(出力数据)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     : 成功时且i_get_value_flg是TRUE时，使用之后释放pp_st_value内存
*******************************************************************************/
int sqlserver_get_datetime(Frbyte_Packet *p_st_data
                          , int i_whole_flg
                          , uint8_t u8_data_type
                          , int i_get_value_flg
                          , Frdata_field **pp_st_value)
{
    int i_ret = 0;
    uint8_t u8_datetime_len = 0;
    uint16_t u16_days = 0;
    uint16_t u16_times = 0;
    uint32_t u32_days = 0;
    uint32_t u32_times = 0;
    int i_days = 0;
    unsigned int ui_year = 0;
    unsigned int ui_month = 0;
    unsigned int ui_day = 0;
    unsigned int ui_hour = 0;
    unsigned int ui_minute = 0;
    unsigned int ui_second = 0;
    unsigned int ui_msecond = 0;
    unsigned int ui_datetime_len = 0;
    time_t t_time = 0;
    struct tm *p_st_time = NULL;
    char *p_datetime = NULL;
    Frdata_field *p_st_value = NULL;

    /* 根据TDS数据类型取得存储datetime的长度 */
    switch (u8_data_type)
    {
        case TDS_DATA_TYPE_DATETIME:
            ui_datetime_len = 8;
            break;

        case TDS_DATA_TYPE_DATETIM4:
            ui_datetime_len = 4;
            break;

        case TDS_DATA_TYPE_DATETIMN:
            /* 1BYTE的TYPE_VARLEN */
            if (bytebuff_remaining(p_st_data) < 1)
            {
                goto error;
            }
            /* 取得长度位,并跳过 */
            bytebuff_get_char(p_st_data, &u8_datetime_len);
            /* 格式判断(For DATETIMNTYPE, only valid lengths are 0x04 and 0x08) */
            if (u8_datetime_len != 0
                && u8_datetime_len != 4
                && u8_datetime_len != 8)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_datetime_len = u8_datetime_len;
            break;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    /* 格式判断(For DATETIMNTYPE, the only valid lengths are 0x04 and 0x08) */
    if (ui_datetime_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        goto error;
    }

    /* 不需要出力具体数据 */
    if (i_get_value_flg == FR_NO)
    {
        *pp_st_value = NULL;
        bytebuff_skip(p_st_data, ui_datetime_len);
        return APM_L7_ANALYZE_SUCC;
    }

    /* 申请出力结构体内存 */
    p_st_value = (Frdata_field *)frmalloc(sizeof(Frdata_field));
    if (p_st_value == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    memset(p_st_value, 0x0, sizeof(Frdata_field));
    p_st_value->em_data_type = FRSTRING;

    /* 根据DateTime所占据的长度来解析数据
    * For DATETIMNTYPE, the only valid lengths are 0x04 and 0x08,
    * which map to smalldatetime and datetime SQL data types respectively.
    */
    switch (ui_datetime_len)
    {
        case 0: /* 数据为空 */
            *pp_st_value = p_st_value;
            return APM_L7_ANALYZE_SUCC;

        case 4: /* 前两位表示从1900年开始的天数，后两位表示一天当中的分钟数 */
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_days
                                       , BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                frfree(p_st_value);
                return APM_L7_ANALYZE_FAIL;
            }
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_times
                                       , BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                frfree(p_st_value);
                return APM_L7_ANALYZE_FAIL;
            }

            /* 日期格式YYYY-MM-DD HH:mm */
            p_datetime = (char *)frmalloc(17 + 1);
            if (p_datetime == NULL)
            {
                frfree(p_st_value);
                return APM_L7_ANALYZE_FAIL;
            }
            memset(p_datetime, 0x0, 18);
            /* One 2-byte unsigned integer that represents the number of days since January 1, 1900 */
            t_time = (u16_days - TDS_0001_1970_DAYS) * 24 * 3600;
            p_st_time = localtime(&t_time);
            ui_year = p_st_time->tm_year + 1900;
            ui_month = p_st_time->tm_mon + 1;
            ui_day = p_st_time->tm_mday;
            /* One 2-byte unsigned integer that represents the number of minutes elapsed since 12 AM that day. */
            ui_hour = u16_times / 60;
            ui_minute = u16_times % 60;
            snprintf(p_datetime, 18, "%04d-%02d-%02dT%02d:%02dZ",ui_year, ui_month, ui_day, ui_hour, ui_minute);
            break;

        case 8: /* 前四位表示从1900年开始的天数，后四位表示一天当中的秒数*300 */
            i_ret = bytebuff_get_int(p_st_data, 4, &u32_days
                                     , BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                frfree(p_st_value);
                return APM_L7_ANALYZE_FAIL;
            }
            i_ret = bytebuff_get_int(p_st_data, 4, &u32_times
                                     , BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                frfree(p_st_value);
                return APM_L7_ANALYZE_FAIL;
            }
            i_days = u32_days;
            /* 日期格式yyyy-MM-dd HH:mm:ss.xxx */
            p_datetime = (char *)frmalloc(24 + 1);
            if (p_datetime == NULL)
            {
                frfree(p_st_value);
                return APM_L7_ANALYZE_FAIL;
            }
            memset(p_datetime, 0x0, 25);
            /*
            * One 4-byte signed integer that represents the number of days since January 1, 1900.
            * Negative numbers are allowed to represent dates since January 1, 1753
            */
            if (i_days == -1) /* 根据java反编译 */
            {
                ui_year = 1970;
                ui_month = 1;
                ui_day = 1;
            }
            else if (i_days < 0)
            {
                //todo
            }
            else
            {
                t_time = (i_days - TDS_0001_1970_DAYS) * 24 * 3600;
                p_st_time = localtime(&t_time);
                ui_year = p_st_time->tm_year + 1900;
                ui_month = p_st_time->tm_mon + 1;
                ui_day = p_st_time->tm_mday;
            }
            /*
            * One 4-byte unsigned integer that represents the number of one three-hundredths of a
            *  second (300 counts per second) elapsed since 12 AM that day.
            */
            if (u32_times != 0xFFFFFFFF) /* 根据java反编译 */
            {
                ui_hour = u32_times / 1080000;
                u32_times -= ui_hour * 1080000;
                ui_minute = u32_times / 18000;
                u32_times -= ui_minute * 18000;
                ui_second = u32_times / 300;
                u32_times -= ui_second * 300;
                ui_msecond = u32_times * 1000 / 300;
            }
            snprintf(p_datetime, 25, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ"
                     ,ui_year, ui_month, ui_day, ui_hour, ui_minute, ui_second, ui_msecond);
            break;
    }

    /* 设置出力 */
    p_st_value->p_field_value = p_datetime;
    *pp_st_value = p_st_value;
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  把Timen的数据转成字符串
*  ARGS     :  pp_inbuffer(入力buffer)
*           :  p_ui_buffer_len(入力buffer的长度)
*           :  ui_scale(scale)
*           :  pp_st_value(出力数据)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_get_times(Frbyte_Packet *p_st_data
                       , LITTLE_BIG_ENDIAN i_endian
                       , int i_whole_flg
                       , int ui_scale
                       , Frdata_field **pp_st_value)
{
    int i_ret = FR_SUCC;
    uint8_t u8_times_len = 0;
    unsigned int ui_len = 0;
    unsigned int ui_loop = 0;
    unsigned int ui_times_len_tmp = 0;
    unsigned long long ull_hour = 0;
    unsigned long long ull_minute = 0;
    unsigned long long ull_second = 0;
    unsigned long long ull_msecond = 0;
    unsigned long long ull_denominator = 0;
    unsigned long long ull_times_value = 0;
    char *p_times = NULL;
    Frdata_field *p_st_value = NULL;
    char arr_buff[5] = {0};

    /* 格式判断 */
    if (bytebuff_remaining(p_st_data) < 1)
    {
        goto error;
    }

    /* 取得长度位,并跳过 */
    bytebuff_get_char(p_st_data, &u8_times_len);

    /* 格式判断 */
    if (u8_times_len > bytebuff_remaining(p_st_data))
    {
        goto error;
    }

    /*
    * SCALE     1    2    3    4    5    6    7
    * LENGTH  0x03 0x03 0x04 0x04 0x04 0x05 0x05
    */
    if (u8_times_len == 3)
    {
        /* 格式判断 */
        if (ui_scale != 1 && ui_scale != 2)
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else if (u8_times_len == 4)
    {
        /* 格式判断 */
        if (ui_scale != 3 && ui_scale != 4)
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else if (u8_times_len == 5)
    {
        /* 格式判断 */
        if (ui_scale != 5 && ui_scale != 6 && ui_scale != 7)
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else if (u8_times_len != 0)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 0时数据位NULL */
    if (u8_times_len != 0)
    {
        i_ret = bytebuff_get_bytes(p_st_data, arr_buff, u8_times_len);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* 取得inter值 */
        ui_times_len_tmp = u8_times_len;
        if (i_endian == BYTE_LITTLE_ENDIAN)
        {
            while (ui_times_len_tmp--)
            {
                ull_times_value = (ull_times_value << 8) | (unsigned char)arr_buff[ui_times_len_tmp];
            }
        }
        else
        {
            while (ui_loop < ui_times_len_tmp)
            {
                ull_times_value = (ull_times_value << 8) | (unsigned char)arr_buff[ui_loop++];
            }
        }
        /* 取得10的scale方 */
        i_ret = __sqlserver_int_pow(10, ui_scale, &ull_denominator);
        if (i_ret == FR_FAIL)
        {
            return APM_L7_ANALYZE_FAIL;
        }

        /* 申请出力结构体内存 */
        p_st_value = (Frdata_field *)frmalloc(sizeof(Frdata_field));
        if (p_st_value == NULL)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        memset(p_st_value, 0x0, sizeof(Frdata_field));
        p_st_value->em_data_type = FRSTRING;

        /* 分配足够内存，时间格式为hh:mm:ss.xxxxxxx */
        ui_len = 16 + 1;
        p_times = (char *)frmalloc(ui_len);
        if (p_times == NULL)
        {
            frfree(p_st_value);
            return APM_L7_ANALYZE_FAIL;
        }

        /* 取得时分秒 */
        ull_msecond = ull_times_value%ull_denominator;
        ull_times_value = ull_times_value/ull_denominator;
        ull_second = ull_times_value%60;
        ull_times_value = ull_times_value/60;
        ull_minute = ull_times_value%60;
        ull_hour = ull_times_value/60;

        switch (ui_scale)
        {
            case 1:
                snprintf(p_times, ui_len, "%02lld:%02lld:%02lld.%01lld", ull_hour, ull_minute, ull_second, ull_msecond);
                break;

            case 2:
                snprintf(p_times, ui_len, "%02lld:%02lld:%02lld.%02lld", ull_hour, ull_minute, ull_second, ull_msecond);
                break;

            case 3:
                snprintf(p_times, ui_len, "%02lld:%02lld:%02lld.%03lld", ull_hour, ull_minute, ull_second, ull_msecond);
                break;

            case 4:
                snprintf(p_times, ui_len, "%02lld:%02lld:%02lld.%04lld", ull_hour, ull_minute, ull_second, ull_msecond);
                break;

            case 5:
                snprintf(p_times, ui_len, "%02lld:%02lld:%02lld.%05lld", ull_hour, ull_minute, ull_second, ull_msecond);
                break;

            case 6:
                snprintf(p_times, ui_len, "%02lld:%02lld:%02lld.%06lld", ull_hour, ull_minute, ull_second, ull_msecond);
                break;

            case 7:
                snprintf(p_times, ui_len, "%02lld:%02lld:%02lld.%07lld", ull_hour, ull_minute, ull_second, ull_msecond);
                break;
        }
        p_st_value->p_field_value = p_times;
    }

     /* 出力设置 */
    *pp_st_value = p_st_value;
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  把DateTimes的数据转成字符串
*  ARGS     :  pp_inbuffer(入力buffer)
*           :  p_ui_buffer_len(入力buffer的长度)
*           :  u8_data_type(TDS数据类型)
*           :  ui_scale(scale)
*           :  pp_st_value(出力数据)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_get_datetimes(Frbyte_Packet *p_st_data
                           , LITTLE_BIG_ENDIAN i_endian
                           , int i_whole_flg
                           , uint8_t u8_data_type
                           , int ui_scale
                           , Frdata_field **pp_st_value)
{
    int i_ret = FR_SUCC;
    unsigned int ui_loop = 0;
    uint8_t u8_datetimes_len = 0;          /* datetimes占据的总长度 */
    /* date */
    time_t t_time = 0;
    unsigned int ui_days_len = 3;               /* date肯定要长度占据三位 */
    unsigned int ui_days_value = 0;             /* 从1900年至今的天数 */
    unsigned int ui_year = 0;
    unsigned int ui_month = 0;
    unsigned int ui_day = 0;
    struct tm *p_st_time = NULL;
    /* time */
    unsigned int ui_times_len = 0;              /* time2占据的长度 */
    unsigned int ui_times_len_tmp = 0;
    unsigned long long ull_times_value = 0;
    unsigned long long ull_denominator = 0;
    unsigned long long ull_hour = 0;
    unsigned long long ull_minute = 0;
    unsigned long long ull_second = 0;
    unsigned long long ull_msecond = 0;
    /* zone */
    unsigned int ui_zone_len = 0;               /* 在DATETIMEOFFSETN时占据两位 */
    uint16_t u16_zone_value = 0;
    short s_zone_value = 0;
    int i_zone_value = 0;
    char c_zone_wps = '+';
    int i_zone = 0;
    int i_mzone = 0;
    /* 入力参数 */
    char *p_datetimes = NULL;
    Frdata_field *p_st_value = NULL;
    char arr_buff[10] = {0};
    char *p_buff = arr_buff;

    /* 格式判断 */
    if (bytebuff_remaining(p_st_data) < 1)
    {
        goto error;
    }

    /* 取得长度位,并跳过 */
    bytebuff_get_char(p_st_data, &u8_datetimes_len);

    /* 格式判断 */
    if (u8_datetimes_len > bytebuff_remaining(p_st_data))
    {
        goto error;
    }
    /* 数据值为空 */
    else if (u8_datetimes_len == 0)
    {
        p_st_value = (Frdata_field *)frmalloc(sizeof(Frdata_field));
        if (p_st_value == NULL)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        memset(p_st_value, 0x0, sizeof(Frdata_field));
        p_st_value->em_data_type = FRSTRING;
        *pp_st_value = p_st_value;
        return APM_L7_ANALYZE_SUCC;
    }

    /* 根据协议判断格式并且取得date，time，zone所占据的长度 */
    switch (u8_data_type)
    {
        case TDS_DATA_TYPE_DATETIME2N:
            /*
            * SCALE     1    2    3    4    5    6    7
            * LENGTH  0x06 0x06 0x07 0x07 0x08 0x08 0x08
            */
            if (u8_datetimes_len == 6)
            {
                /* 格式判断 */
                if (ui_scale != 1 && ui_scale != 2)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
            }
            else if (u8_datetimes_len == 7)
            {
                /* 格式判断 */
                if (ui_scale != 3 && ui_scale != 4)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
            }
            else if (u8_datetimes_len == 8)
            {
                /* 格式判断 */
                if (ui_scale != 5 && ui_scale != 6 && ui_scale != 7)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
            }
            else
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* 取得time占据的长度 */
            ui_times_len = u8_datetimes_len - ui_days_len;
            break;

        case TDS_DATA_TYPE_DATETIMEOFFSETN:
            /*
            * SCALE     1    2    3    4    5    6    7
            * LENGTH  0x08 0x08 0x09 0x09 0x0A 0x0A 0x0A
            */
            if (u8_datetimes_len == 8)
            {
                if (ui_scale != 1 && ui_scale != 2)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
            }
            else if (u8_datetimes_len == 9)
            {
                /* 格式判断 */
                if (ui_scale != 3 && ui_scale != 4)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
            }
            else if (u8_datetimes_len == 10)
            {
                /* 格式判断 */
                if (ui_scale != 5 && ui_scale != 6 && ui_scale != 7)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
            }
            else
            {
                return APM_L7_ANALYZE_FAIL;
            }

            /* 数据类型是DATETIMEOFFSET时，拥有2位的zone */
            ui_zone_len = 2;
            /* 取得time占据的长度 */
            ui_times_len = u8_datetimes_len - ui_days_len - ui_zone_len;
            break;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    i_ret = bytebuff_get_bytes(p_st_data, arr_buff, u8_datetimes_len - ui_zone_len);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 申请出力结构体内存 */
    p_st_value = (Frdata_field *)frmalloc(sizeof(Frdata_field));
    if (p_st_value == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    memset(p_st_value, 0x0, sizeof(Frdata_field));
    p_st_value->em_data_type = FRSTRING;
    /* 分配足够内存,时间格式YYYY-MM-DD hh:mm:ss.xxxxxxx +XX:XX(例2014-11-04 12:12:00.0000000 +08:00) */
    p_datetimes = (char *)frmalloc(35 + 1);
    if (p_datetimes == NULL)
    {
        frfree(p_st_value);
        return APM_L7_ANALYZE_FAIL;
    }
    p_st_value->p_field_value = p_datetimes;

    /* date，time，zone所在数据块上的先后位置是：time date zone */
    /* 先取得time */
    ui_times_len_tmp = ui_times_len;
    if (i_endian == BYTE_LITTLE_ENDIAN)
    {
        while (ui_times_len_tmp--)
        {
            ull_times_value = (ull_times_value << 8) | (unsigned char)arr_buff[ui_times_len_tmp];
        }
    }
    else
    {
        while (ui_loop < ui_times_len_tmp)
        {
            ull_times_value = (ull_times_value << 8) | (unsigned char)arr_buff[ui_loop++];
        }
    }
    p_buff += u8_datetimes_len;
    i_ret = __sqlserver_int_pow(10, ui_scale, &ull_denominator);
    if (i_ret == FR_FAIL)
    {
        frfree(p_datetimes);
        frfree(p_st_value);
        return APM_L7_ANALYZE_FAIL;
    }
    /* 根据time值和scale取得时分秒 */
    ull_msecond = ull_times_value%ull_denominator;
    ull_times_value = ull_times_value/ull_denominator;
    ull_second = ull_times_value%60;
    ull_times_value = ull_times_value/60;
    ull_minute = ull_times_value%60;
    ull_hour = ull_times_value/60;

    /* 再取得date */
    ui_loop = 0;
    if (i_endian == BYTE_LITTLE_ENDIAN)
    {
        while (ui_days_len--)
        {
            ui_days_value = (ui_days_value << 8) | (unsigned char)arr_buff[ui_times_len + ui_days_len];
        }
    }
    else
    {
        while (ui_loop < ui_days_len)
        {
            ui_days_value = (ui_days_value << 8) | (unsigned char)arr_buff[ui_times_len + ui_loop++];
        }
    }
    p_buff += 3;
    /* 根据date值成年月日 */
    t_time = (ui_days_value - TDS_0001_1970_DAYS) * 24 * 3600;
    p_st_time = localtime(&t_time);
    ui_year = p_st_time->tm_year + 1900;
    ui_month = p_st_time->tm_mon + 1;
    ui_day = p_st_time->tm_mday;

    /* 格式化出力年月日 时分秒 */
    switch (ui_scale)
    {
        case 1:
            snprintf(p_datetimes, 36, "%04d-%02d-%02dT%02lld:%02lld:%02lld.%01lldZ"
                     , ui_year, ui_month, ui_day, ull_hour, ull_minute, ull_second, ull_msecond);
            break;

        case 2:
            snprintf(p_datetimes, 36, "%04d-%02d-%02dT%02lld:%02lld:%02lld.%02lldZ"
                     , ui_year, ui_month, ui_day, ull_hour, ull_minute, ull_second, ull_msecond);
            break;

        case 3:
            snprintf(p_datetimes, 36, "%04d-%02d-%02dT%02lld:%02lld:%02lld.%03lldZ"
                     , ui_year, ui_month, ui_day, ull_hour, ull_minute, ull_second, ull_msecond);
            break;

        case 4:
            snprintf(p_datetimes, 36, "%04d-%02d-%02dT%02lld:%02lld:%02lld.%04lldZ"
                     , ui_year, ui_month, ui_day, ull_hour, ull_minute, ull_second, ull_msecond);
            break;

        case 5:
            snprintf(p_datetimes, 36, "%04d-%02d-%02dT%02lld:%02lld:%02lld.%05lldZ"
                     , ui_year, ui_month, ui_day, ull_hour, ull_minute, ull_second, ull_msecond);
            break;

        case 6:
            snprintf(p_datetimes, 36, "%04d-%02d-%02dT%02lld:%02lld:%02lld.%06lldZ"
                     , ui_year, ui_month, ui_day, ull_hour, ull_minute, ull_second, ull_msecond);
            break;

        case 7:
            snprintf(p_datetimes, 36, "%04d-%02d-%02dT%02lld:%02lld:%02lld.%07lldZ"
                     , ui_year, ui_month, ui_day, ull_hour, ull_minute, ull_second, ull_msecond);
            break;

        default:
            sqlserver_free((void **)&p_datetimes);
            return APM_L7_ANALYZE_FAIL;

    }
    p_datetimes += strlen(p_datetimes);

    /* 最后根据是否有zone取得zone */
    if (ui_zone_len)
    {
        /* 有市区时不要结尾的Z */
        p_datetimes--;
        i_ret = bytebuff_get_short(p_st_data, 2, &u16_zone_value, i_endian);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        s_zone_value = (short)u16_zone_value;
        i_zone_value = s_zone_value;
        if (i_zone_value < 0)
        {
            c_zone_wps = '-';
            i_zone_value = abs(i_zone_value);
        }
        i_zone = i_zone_value/60;
        i_mzone = i_zone_value%60;
        snprintf(p_datetimes, 36, "%c%02d:%02d", c_zone_wps, i_zone, i_mzone);
    }

    /* 出力设置 */
    *pp_st_value = p_st_value;
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  取得UniqueIdentifier数据
*  ARGS     :  pp_inbuffer(入力buffer)
*           :  p_ui_buffer_len(入力buffer的长度)
*           :  u8_data_type(数据类型)
*           :  pp_st_value(出力数据)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_get_guid(Frbyte_Packet *p_st_data
                      , int i_whole_flg
                      , uint8_t u8_data_type
                      , Frdata_field **pp_st_value)
{
    int i_ret = 0;
    uint8_t u8_binary_len = 0;
    int i_loop = 0;
    int i_value_len = 0;
    char *p_guid = NULL;
    char arr_swap[16];
    char arr_buff[16] = {0};
    char *p_buff = arr_buff;
    char *p_tmp_buffer = NULL;
    Frdata_field *p_st_value = NULL;

    /* 所能处理的数据类型(GUID) */
    switch (u8_data_type)
    {
        case TDS_DATA_TYPE_GUID:
            /* 1BYTE的TYPE_VARLEN */
            if (bytebuff_remaining(p_st_data) < 1)
            {
                goto error;
            }
            /* 取得长度位,并跳过 */
            bytebuff_get_char(p_st_data, &u8_binary_len);
            break;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    /* 格式判断 */
    if (u8_binary_len > bytebuff_remaining(p_st_data))
    {
        goto error;
    }

    /* if length is 16, need to swap some bytes for correct text version */
    if (u8_binary_len == 16)
    {
        i_ret = bytebuff_get_bytes(p_st_data, arr_buff, 16);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        memset(arr_swap, 0x00, sizeof(arr_swap));
        arr_swap[3] = arr_buff[0];
        arr_swap[2] = arr_buff[1];
        arr_swap[1] = arr_buff[2];
        arr_swap[0] = arr_buff[3];
        arr_swap[5] = arr_buff[4];
        arr_swap[4] = arr_buff[5];
        arr_swap[7] = arr_buff[6];
        arr_swap[6] = arr_buff[7];
        p_tmp_buffer = arr_swap;
        memcpy(p_tmp_buffer + 8, p_buff + 8, 8);
    }
    else if (u8_binary_len != 0)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 申请出力结构体内存 */
    p_st_value = (Frdata_field *)frmalloc(sizeof(Frdata_field));
    if (p_st_value == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    memset(p_st_value, 0x0, sizeof(Frdata_field));
    p_st_value->em_data_type = FRSTRING;

    /* 0时值为NULL */
    if (u8_binary_len > 0)
    {
        /* 申请足够内存 */
        i_value_len = u8_binary_len * 3 + 1;
        p_guid = (char *)frmalloc(i_value_len);
        if (p_guid == NULL)
        {
            frfree(p_st_value);
            return APM_L7_ANALYZE_FAIL;
        }
        p_st_value->p_field_value = p_guid;
        /* 做成值 */
        while (i_loop < u8_binary_len)
        {
            snprintf(p_guid, i_value_len, "%02X", *p_tmp_buffer);
            i_value_len -= 2;
            p_guid += 2;
            p_tmp_buffer++;
            if (i_loop == 3 || i_loop == 5 || i_loop == 7 || i_loop == 9)
            {
                *p_guid = '-';
                p_guid++;
            }
            i_loop++;
        }
        p_guid = '\0';
    }

    /* 出力设置 */
    *pp_st_value = p_st_value;
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  取得相应精度数值
*  ARGS     :  pp_inbuffer(入力buffer)
*           :  p_ui_buffer_len(入力buffer的长度)
*           :  ui_scale(小数位数)
*           :  pp_st_value(出力数据)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_get_dec(Frbyte_Packet *p_st_data
                     , LITTLE_BIG_ENDIAN i_endian
                     , int i_whole_flg
                     , unsigned int ui_scale
                     , Frdata_field **pp_st_value)
{
    uint8_t u8_dec_len = 0;
    uint8_t u8_sign = 0;
    int i_dec_len_tmp = 0;
    int i_sign = 1;
    uint32_t u32_4byte_value = 0;
    char *p_dec = NULL;
    char arr_low[MSSQL_16BYTE_MAX_LEN + 1];
    char arr_high[MSSQL_16BYTE_MAX_LEN + 1];
    char arr_result[MSSQL_16BYTE_MAX_LEN + 1];
    char arr_result_tmp[MSSQL_16BYTE_MAX_LEN + 1];
    memset(arr_low, 0x0, sizeof(arr_low));
    memset(arr_high, 0x0, sizeof(arr_high));
    memset(arr_result, 0x0, sizeof(arr_result));
    memset(arr_result_tmp, 0x0, sizeof(arr_result_tmp));
    Frdata_field *p_st_value = NULL;

    /* 格式判断 */
    if (1 > bytebuff_remaining(p_st_data))
    {
        goto error;
    }
    /* 取得长度位,并跳过 */
    bytebuff_get_char(p_st_data, &u8_dec_len);
    if (u8_dec_len != 0 && u8_dec_len != 5 && u8_dec_len != 9
        && u8_dec_len != 13 && u8_dec_len != 17)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 格式判断(1位的符号位+4/8/12/16的数据位) */
    if (u8_dec_len > bytebuff_remaining(p_st_data))
    {
        goto error;
    }

    /* 值为NULL */
    i_dec_len_tmp = u8_dec_len;
    if (u8_dec_len == 0)
    {
        p_st_value = (Frdata_field *)frmalloc(sizeof(Frdata_field));
        if (p_st_value == NULL)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        memset(p_st_value, 0x0, sizeof(Frdata_field));
        p_st_value->em_data_type = FRSTRING;
        *pp_st_value = p_st_value;
        return APM_L7_ANALYZE_SUCC;
    }

    /* 取得符号位 */
    bytebuff_get_char(p_st_data, &u8_sign);
    if (u8_sign == 0)
    {
        i_sign = 0;  /* 负数 */
    }
    else
    {
        i_sign = 1;   /* 无符号 */
    }
    /* 越过符号位 */
    u8_dec_len--;

    /* 申请出力结构体内存 */
    p_st_value = (Frdata_field *)frmalloc(sizeof(Frdata_field));
    if (p_st_value == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    memset(p_st_value, 0x0, sizeof(Frdata_field));
    p_st_value->em_data_type = FRSTRING;

    /* 第一位是符号位，后面的是数据位(只允许4,8,12,16) */
    switch (u8_dec_len)
    {
        /* 4byte/8byte/12byte/16byte的数据位 */
        case 4:
        case 8:
        case 12:
        case 16:
            /* 申请足够长内存(.和\0） */
            p_dec = (char *)frmalloc((ui_scale + MSSQL_16BYTE_MAX_LEN) * 2 + 1);
            if (p_dec == NULL)
            {
                frfree(p_st_value);
                return APM_L7_ANALYZE_SUCC;
            }
            memset(p_dec, 0x0, (ui_scale + MSSQL_16BYTE_MAX_LEN) * 2 + 1);
            p_st_value->p_field_value = p_dec;
            /* 取得第一个四位 */
            bytebuff_get_int(p_st_data, 4, &u32_4byte_value, i_endian);
            u8_dec_len -= 4;
            if (u8_dec_len > 0)
            {
                snprintf(arr_low, MSSQL_16BYTE_MAX_LEN, "%u", u32_4byte_value);
                /* 取得第二个四位 */
                bytebuff_get_int(p_st_data, 4, &u32_4byte_value, i_endian);
                u8_dec_len -= 4;
                snprintf(arr_high, MSSQL_16BYTE_MAX_LEN, "%u", u32_4byte_value);
                /* 取得8位的数值结果 */
                __sqlserver_bigint_multi(MSSQL_4BYTE_MAX_VALUE, arr_high, arr_result_tmp);
                __sqlserver_bigint_add(arr_low, arr_result_tmp, arr_result);
                if (u8_dec_len > 0)
                {
                    snprintf(arr_low, MSSQL_16BYTE_MAX_LEN, "%s", arr_result);
                    /* 取得第三个四位 */
                    bytebuff_get_int(p_st_data, 4, &u32_4byte_value, i_endian);
                    u8_dec_len -= 4;
                    snprintf(arr_high, MSSQL_16BYTE_MAX_LEN, "%u", u32_4byte_value);
                    /* 取得12位的数值结果 */
                    memset(arr_result, 0x0, sizeof(arr_result));
                    memset(arr_result_tmp, 0x0, sizeof(arr_result_tmp));
                    __sqlserver_bigint_multi(MSSQL_8BYTE_MAX_VALUE, arr_high, arr_result_tmp);
                    __sqlserver_bigint_add(arr_low, arr_result_tmp, arr_result);
                    if (u8_dec_len > 0)
                    {
                        snprintf(arr_low, MSSQL_16BYTE_MAX_LEN, "%s", arr_result);
                        /* 取得第四个四位 */
                        bytebuff_get_int(p_st_data, 4, &u32_4byte_value, BYTE_LITTLE_ENDIAN);
                        snprintf(arr_high, MSSQL_16BYTE_MAX_LEN, "%u", u32_4byte_value);
                        /* 取得12位的数值结果 */
                        memset(arr_result, 0x0, sizeof(arr_result));
                        memset(arr_result_tmp, 0x0, sizeof(arr_result_tmp));
                        __sqlserver_bigint_multi(MSSQL_12BYTE_MAX_VALUE, arr_high, arr_result_tmp);
                        __sqlserver_bigint_add(arr_low, arr_result_tmp, arr_result);
                    }
                }
            }
            else  /* 4byte值 */
            {
                snprintf(arr_result, MSSQL_16BYTE_MAX_LEN, "%u", u32_4byte_value);
            }
            break;

        default:
            break;
    }

    /* 符号位 */
    if (i_sign == 0)
    {
        *p_dec = '-';
        p_dec++;
    }

    if (i_dec_len_tmp == 0)
    {
        p_st_value->p_field_value = NULL;
    }
    else if (ui_scale == 0) /* 根据scale做成最终结果 */
    {
        strncpy(p_dec, arr_result, sizeof(arr_result));
    }
    else if (strlen(arr_result) <= ui_scale) /* 前补0 */
    {
        *p_dec = '0';
        *(p_dec + 1) = '.';
        memset(p_dec + 2, '0', ui_scale - 1);
        strncpy(p_dec + ui_scale + 1, arr_result, sizeof(arr_result));
    }
    else
    {
        strncpy(p_dec, arr_result, sizeof(arr_result));
        memmove(p_dec + strlen(arr_result) - ui_scale + 1
                , p_dec + strlen(arr_result) - ui_scale
                , ui_scale);
        p_dec[strlen(arr_result) - ui_scale] = '.';
    }

    /* 出力设置 */
    *pp_st_value = p_st_value;
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析TYPE_VARBYTE
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  u8_data_type(当前typeinfo是属于RPC的还是COLMETADATA的)
*           :  ui_precision(precision)
*           :  ui_scale(scale)
*           :  i_partlentype(当前data type是否属于PLP)
*           :  pp_st_value(出力数据)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :  函数成功返回时，当pp_value不为NULL时注意使用完后释放内存
*******************************************************************************/
int sqlserver_get_type_varbyte(Frbyte_Packet *p_st_data
                               , L7session_sqlserver *p_st_sess
                               , int i_whole_flg
                               , uint8_t u8_data_type
                               , uint8_t ui_precision
                               , uint8_t ui_scale
                               , int i_partlentype
                               , Frdata_field **pp_st_value)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint64_t u64_len = 0;
    uint32_t u32_len = 0;
    unsigned int ui_skip_len = 0;
    Frdata_field *p_st_value = NULL;
    *pp_st_value = NULL;

    /* PLP类型 */
    if (i_partlentype == FR_YES)
    {
        if (bytebuff_remaining(p_st_data) < 8)
        {
            goto error;
        }
        /* get length */
        i_ret = bytebuff_get_long(p_st_data, 8, &u64_len, BYTE_LITTLE_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }

        /* PLP_NULL = %xFFFFFFFFFFFFFFFF */
        if (u64_len == 0xFFFFFFFFFFFFFFFFULL)
        {
            /* 设置出力 */
            p_st_value = (Frdata_field *)frmalloc(sizeof(Frdata_field));
            if (p_st_value == NULL)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            memset(p_st_value, 0x0, sizeof(Frdata_field));
            p_st_value->em_data_type = FRBLOB;
            p_st_value->p_field_value = NULL;
            *pp_st_value = p_st_value;
            return APM_L7_ANALYZE_SUCC;
        }
        else
        {
            while (1)
            {
                if (bytebuff_remaining(p_st_data) < 4)
                {
                    goto error;
                }
                /* get length */
                i_ret = bytebuff_get_int(p_st_data, 4, &u32_len
                                        , BYTE_LITTLE_ENDIAN);
                if (i_ret != FR_SUCC)
                {
                    return APM_L7_ANALYZE_FAIL;
                }

                /* 以0x00000000结尾 */
                if (u32_len == 0)
                {
                    p_st_value = (Frdata_field *)frmalloc(sizeof(Frdata_field));
                    if (p_st_value == NULL)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                    memset(p_st_value, 0x0, sizeof(Frdata_field));
                    p_st_value->em_data_type = FRBLOB;
                    p_st_value->p_field_value = frstrdup(MSSQL_BLOB_DATA);
                    *pp_st_value = p_st_value;
                    return APM_L7_ANALYZE_SUCC;
                }

                /* 格式判断 */
                if (u32_len <= (unsigned int)bytebuff_remaining(p_st_data))
                {
                    /* 跳过当前值 */
                    bytebuff_skip(p_st_data, u32_len);
                }
                else
                {
                    /* 设置需要跳过的长度 */
                    ui_skip_len = u32_len - bytebuff_remaining(p_st_data);
                    bytebuff_set_skip(p_st_data, ui_skip_len);
                    goto error;
                }
            }
        }
    }
    else
    {
        switch(u8_data_type)
        {
            /* Null (no data associated with this type) */
            case TDS_DATA_TYPE_NULL:
                *pp_st_value = (Frdata_field *)frmalloc(sizeof(Frdata_field));
                if (*pp_st_value == NULL)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                memset(*pp_st_value, 0x0, sizeof(Frdata_field));
                (*pp_st_value)->em_data_type = FRSTRING;
                break;

            /*
            * 根据协议解析以及java驱动分析结果，需要注意以下事项：
            * 1: 数据类型INT1为占据1BYTE的无符号数值
            * 2: INTN中lengths是0x01的数值却是有符号的
            * 3：其他类型的INT都为有符号的数值
            */
            case TDS_DATA_TYPE_INT1:
                i_ret = frtds_convert_to_int(p_st_data, i_whole_flg
                                            , p_st_sess->i_endian
                                            , 1, FR_YES, pp_st_value);
                break;

            case TDS_DATA_TYPE_INT2:
                i_ret = frtds_convert_to_int(p_st_data, i_whole_flg
                                            , p_st_sess->i_endian
                                            , 2, FR_NO, pp_st_value);
                break;

            case TDS_DATA_TYPE_INT4:
                i_ret = frtds_convert_to_int(p_st_data, i_whole_flg
                                            , p_st_sess->i_endian
                                            , 4, FR_NO, pp_st_value);
                break;

            case TDS_DATA_TYPE_INT8:
                i_ret = frtds_convert_to_int(p_st_data, i_whole_flg
                                            , p_st_sess->i_endian
                                            , 8, FR_NO, pp_st_value);
                break;

            /*
            * For INTNTYPE, the only valid lengths are 0x01, 0x02, 0x04,
            * and 0x08, which map to tinyint, smallint, int, and bigint
            * SQL data types respectively.
            */
            case TDS_DATA_TYPE_INTN:
                i_ret = frtds_convert_to_intn(p_st_data, i_whole_flg
                                             , p_st_sess->i_endian
                                             , FR_NO, pp_st_value);
                break;

            /* 取得utf8字符串 */
            case TDS_DATA_TYPE_CHAR:            /* Char (legacy support) */
            case TDS_DATA_TYPE_VARCHAR:         /* VarChar (legacy support) */
            case TDS_DATA_TYPE_BIGVARCHR:       /* VarChar */
            case TDS_DATA_TYPE_BIGCHAR:         /* Char */
            case TDS_DATA_TYPE_NVARCHAR:        /* NVarChar */
            case TDS_DATA_TYPE_NCHAR:           /* NChar */
            case TDS_DATA_TYPE_TEXT:            /* Text */
            case TDS_DATA_TYPE_NTEXT:           /* NText */
                i_ret = sqlserver_get_utf8str(p_st_data, i_whole_flg
                                             , p_st_sess->arr_client_charset
                                             , u8_data_type, pp_st_value);
                break;

            /* 取得binary串 */
            case TDS_DATA_TYPE_BINARY:           /* Binary (legacy support) */
            case TDS_DATA_TYPE_VARBINARY:        /* VarBinary (legacy support) */
            case TDS_DATA_TYPE_BIGVARBIN:        /* VarBinary */
            case TDS_DATA_TYPE_BIGBINARY:        /* Binary */
            case TDS_DATA_TYPE_IMAGE:            /* Image */
            case TDS_DATA_TYPE_SSVARIANT:
                i_ret = sqlserver_get_binary(p_st_data, i_whole_flg
                                            , u8_data_type, pp_st_value);
                break;

            /* 取得MONEY串 */
            case TDS_DATA_TYPE_MONEY:            /* Money (8 byte data representation) */
                i_ret = frtds_convert_to_money(p_st_data, i_whole_flg
                                              , p_st_sess->i_endian
                                              , 8, pp_st_value);
                break;

            case TDS_DATA_TYPE_MONEY4:           /* Money (4 byte data representation) */
                i_ret = frtds_convert_to_money(p_st_data, i_whole_flg
                                              , p_st_sess->i_endian
                                              , 4, pp_st_value);
                break;

            case TDS_DATA_TYPE_MONEYN:
                i_ret = frtds_convert_to_moneyn(p_st_data, i_whole_flg
                                               , p_st_sess->i_endian
                                               , pp_st_value);
                break;

            /* 取得时间数据: DATETIM4和DATETIME和DATETIMN既有日期也有时分秒 */
            case TDS_DATA_TYPE_DATETIM4:          /* SmallDateTime (4 byte data representation) */
                i_ret = frtds_convert_to_datetime(p_st_data, 4
                                                 , p_st_sess->i_endian
                                                 , i_whole_flg, pp_st_value);
                break;

            case TDS_DATA_TYPE_DATETIME:          /* DateTime (8 byte data representation) */
                i_ret = frtds_convert_to_datetime(p_st_data, 8
                                                 , p_st_sess->i_endian
                                                 , i_whole_flg, pp_st_value);
                break;

            case TDS_DATA_TYPE_DATETIMN:
                i_ret = frtds_convert_to_datetimen(p_st_data, p_st_sess->i_endian
                                                  , i_whole_flg, pp_st_value);
                break;

            /* For DATENTYPE, the only valid lengths are 0x03 for non-NULL instances and 0x00 for NULL instances */
            /* date is represented as one 3-byte unsigned integer that represents the number of days sinc January 1, year 1. */
            case TDS_DATA_TYPE_DATEN:
                i_ret = frtds_convert_to_daten(p_st_data, p_st_sess->i_endian
                                              , FRTDS_MSSQL, i_whole_flg
                                              , pp_st_value);
                break;

            /* 取得时间数据: DATEN只有时分秒没有日期 */
            /* For TIMENTYPE, the only valid lengths are 0x03, 0x04, 0x05 */
            case TDS_DATA_TYPE_TIMEN:
                i_ret = sqlserver_get_times(p_st_data, p_st_sess->i_endian
                                            ,i_whole_flg, ui_scale, pp_st_value);
                break;

            case TDS_DATA_TYPE_DATETIME2N:            /* (introduced in TDS 7.3) */
            case TDS_DATA_TYPE_DATETIMEOFFSETN:       /* (introduced in TDS 7.3) */
                 i_ret = sqlserver_get_datetimes(p_st_data, p_st_sess->i_endian
                                                , i_whole_flg, u8_data_type
                                                , ui_scale, pp_st_value);
                 break;

            /* 取得boolean型数据 */
            case TDS_DATA_TYPE_BIT:               /* Bit (1 byte data representation) */
                i_ret = frtds_convert_to_boolean(p_st_data, i_whole_flg, pp_st_value);
                 break;

            case TDS_DATA_TYPE_BITN:
                i_ret = frtds_convert_to_booleann(p_st_data, i_whole_flg, pp_st_value);
                break;

            /* 取得浮点型数据 */
            case TDS_DATA_TYPE_FLT4:             /* Real (4 byte data representation) */
                i_ret = frtds_convert_to_float(p_st_data, 4
                                               , p_st_sess->i_float_type
                                               , i_whole_flg, pp_st_value);
                break;

            case TDS_DATA_TYPE_FLT8:             /* Float (8 byte data representation) */
                i_ret = frtds_convert_to_float(p_st_data, 8
                                               , p_st_sess->i_float_type
                                               , i_whole_flg, pp_st_value);
                break;

            case TDS_DATA_TYPE_FLTN:
                i_ret = frtds_convert_to_floatn(p_st_data, p_st_sess->i_float_type
                                               , i_whole_flg, pp_st_value);
                break;

            /* 取得UniqueIdentifier数据 */
            case TDS_DATA_TYPE_GUID:              /* UniqueIdentifier */
                i_ret = sqlserver_get_guid(p_st_data, i_whole_flg
                                           , u8_data_type, pp_st_value);
                break;

            /* integer part MUST be either 4, 8, 12, or 16 bytes */
            case TDS_DATA_TYPE_DECIMALN:         /* Decimal */
            case TDS_DATA_TYPE_NUMERICN:         /* Numeric */
            case TDS_DATA_TYPE_DECIMAL:          /* Decimal (legacy support) */
            case TDS_DATA_TYPE_NUMERIC:          /* Numeric (legacy support) */
                i_ret = sqlserver_get_dec(p_st_data, p_st_sess->i_endian
                                          , i_whole_flg, ui_scale, pp_st_value);
                break;

            default:
                return APM_L7_ANALYZE_FAIL;
        }
    }

    /* 正常时设置出力 */
    return i_ret;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析TYPE_VARBYTE
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  u8_data_type(当前typeinfo是属于RPC的还是COLMETADATA的)
*           :  i_get_value_flg(在未知版本的情况取得较为可信的版本)
*           :  ui_precision(precision)
*           :  ui_scale(scale)
*           :  i_partlentype(当前data type是否属于PLP)
*           :  pp_st_value(出力数据)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :  函数成功返回时，当pp_value不为NULL时注意使用完后释放内存
*******************************************************************************/
int sqlserver_skip_type_varbyte(Frbyte_Packet *p_st_data
                                , int i_whole_flg
                                , uint8_t u8_data_type
                                , uint8_t ui_precision
                                , uint8_t ui_scale
                                , int i_partlentype)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint64_t u64_len = 0;
    uint32_t u32_len = 0;
    unsigned int ui_skip_len = 0;

    /* PLP类型 */
    if (i_partlentype == FR_YES)
    {
        if (bytebuff_remaining(p_st_data) < 8)
        {
            goto error;
        }
        /* get length */
        i_ret = bytebuff_get_long(p_st_data, 8, &u64_len, BYTE_LITTLE_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }

        /* PLP_NULL = %xFFFFFFFFFFFFFFFF */
        if (u64_len == 0xFFFFFFFFFFFFFFFFULL)
        {
            return APM_L7_ANALYZE_SUCC;
        }
        else
        {
            while (1)
            {
                if (bytebuff_remaining(p_st_data) < 4)
                {
                    goto error;
                }
                /* get length */
                i_ret = bytebuff_get_int(p_st_data, 4, &u32_len, BYTE_LITTLE_ENDIAN);
                if (i_ret != FR_SUCC)
                {
                    return APM_L7_ANALYZE_FAIL;
                }

                /* 以0x00000000结尾 */
                if (u32_len == 0)
                {
                    return APM_L7_ANALYZE_SUCC;
                }

                /* 格式判断 */
                if (u32_len <= (unsigned int)bytebuff_remaining(p_st_data))
                {
                    /* 跳过当前值 */
                    bytebuff_skip(p_st_data, u32_len);
                }
                else
                {
                    /* 设置需要跳过的长度 */
                    ui_skip_len = u32_len - bytebuff_remaining(p_st_data);
                    bytebuff_set_skip(p_st_data, ui_skip_len);
                    goto error;
                }
            }
        }
    }
    else
    {
        switch(u8_data_type)
        {
            /* Null (no data associated with this type) */
            case TDS_DATA_TYPE_NULL:
                break;

            /*
            * 根据协议解析以及java驱动分析结果，需要注意以下事项：
            * 1: 数据类型INT1为占据1BYTE的无符号数值
            * 2: INTN中lengths是0x01的数值却是有符号的
            * 3：其他类型的INT都为有符号的数值
            */
            case TDS_DATA_TYPE_INT1:
            case TDS_DATA_TYPE_BIT:               /* Bit (1 byte data representation) */
                i_ret = frtds_skip_fixed_len(p_st_data, i_whole_flg, 1);
                break;

            case TDS_DATA_TYPE_INT2:
                i_ret = frtds_skip_fixed_len(p_st_data, i_whole_flg, 2);
                break;

            case TDS_DATA_TYPE_INT4:
            case TDS_DATA_TYPE_MONEY4:           /* Money (4 byte data representation) */
            case TDS_DATA_TYPE_DATETIM4:         /* SmallDateTime (4 byte data representation) */
            case TDS_DATA_TYPE_FLT4:             /* Real (4 byte data representation) */
                i_ret = frtds_skip_fixed_len(p_st_data, i_whole_flg, 4);
                break;

            case TDS_DATA_TYPE_INT8:
            case TDS_DATA_TYPE_MONEY:            /* Money (8 byte data representation) */
            case TDS_DATA_TYPE_DATETIME:         /* DateTime (8 byte data representation) */
            case TDS_DATA_TYPE_FLT8:             /* Float (8 byte data representation) */
                i_ret = frtds_skip_fixed_len(p_st_data, i_whole_flg, 8);
                break;

            /*
            * For INTNTYPE, the only valid lengths are 0x01, 0x02, 0x04,
            * and 0x08, which map to tinyint, smallint, int, and bigint
            * SQL data types respectively.
            */
            case TDS_DATA_TYPE_INTN:
            case TDS_DATA_TYPE_CHAR:             /* Char (legacy support) */
            case TDS_DATA_TYPE_VARCHAR:          /* VarChar (legacy support) */
            case TDS_DATA_TYPE_BINARY:           /* Binary (legacy support) */
            case TDS_DATA_TYPE_VARBINARY:        /* VarBinary (legacy support) */
            case TDS_DATA_TYPE_MONEYN:
            case TDS_DATA_TYPE_DATETIMN:
            /* For DATENTYPE, the only valid lengths are 0x03 for non-NULL instances and 0x00 for NULL instances */
            /* date is represented as one 3-byte unsigned integer that represents the number of days sinc January 1, year 1. */
            case TDS_DATA_TYPE_DATEN:            /* For TIMENTYPE, the only valid lengths are 0x03, 0x04, 0x05 */
            case TDS_DATA_TYPE_TIMEN:
            case TDS_DATA_TYPE_DATETIME2N:       /* (introduced in TDS 7.3) */
            case TDS_DATA_TYPE_DATETIMEOFFSETN:  /* (introduced in TDS 7.3) */
            case TDS_DATA_TYPE_BITN:
            case TDS_DATA_TYPE_FLTN:
            case TDS_DATA_TYPE_GUID:             /* UniqueIdentifier */
            case TDS_DATA_TYPE_DECIMALN:         /* Decimal */
            case TDS_DATA_TYPE_NUMERICN:         /* Numeric */
            case TDS_DATA_TYPE_DECIMAL:          /* Decimal (legacy support) */
            case TDS_DATA_TYPE_NUMERIC:          /* Numeric (legacy support) */
                i_ret = frtds_skip_var_len(p_st_data, i_whole_flg
                                          , BYTE_LITTLE_ENDIAN, 1);
                break;

            case TDS_DATA_TYPE_BIGVARCHR:        /* VarChar */
            case TDS_DATA_TYPE_BIGCHAR:          /* Char */
            case TDS_DATA_TYPE_NVARCHAR:         /* NVarChar */
            case TDS_DATA_TYPE_NCHAR:            /* NChar */
            case TDS_DATA_TYPE_BIGVARBIN:        /* VarBinary */
            case TDS_DATA_TYPE_BIGBINARY:        /* Binary */
                i_ret = sqlserver_skip_var_len(p_st_data, i_whole_flg
                                              , BYTE_LITTLE_ENDIAN, 2);
                break;

            case TDS_DATA_TYPE_TEXT:             /* Text */
            case TDS_DATA_TYPE_NTEXT:            /* NText */
            case TDS_DATA_TYPE_IMAGE:            /* Image */
            case TDS_DATA_TYPE_SSVARIANT:
                i_ret = sqlserver_skip_var_len(p_st_data, i_whole_flg
                                              , BYTE_LITTLE_ENDIAN, 4);
                break;

            default:
                return APM_L7_ANALYZE_FAIL;
        }
    }

    /* 正常时设置出力 */
    return i_ret;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析RPC parameter
*  ARGS     :  pp_inbuffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  p_i_may_tds_ver(可能的TDS版本号)
*           :  pp_st_value(参数值)
*           :  p_i_ref_flg(该参数是入参还是出参)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_get_rpc_param(Frbyte_Packet *p_st_data
                            , L7session_sqlserver *p_st_sess
                            , int i_whole_flg
                            , int *p_i_may_tds_ver
                            , Frdata_field **pp_st_value
                            , int *p_i_ref_flg)
{
    int i_ret = APM_L7_ANALYZE_TODO;
    uint8_t u8_name_len = 0;
    unsigned int ui_name_len = 0;
    uint8_t u8_status_flag = 0;
    uint8_t u8_data_type = 0;
    uint8_t u8_precision = 0;
    uint8_t u8_scale = 0;
    int i_partlentype = FR_NO;

    /* 取得参数名称(TDS定义：B_VARCHAR = BYTELEN *CHAR) */
    if (bytebuff_remaining(p_st_data))
    {
        /* 此处的长度是实际UTF-8时的长度，故实际所占据packet的位数是长度的2倍 */
        bytebuff_get_char(p_st_data, &u8_name_len);
        ui_name_len = u8_name_len * 2;
        if (ui_name_len <= (unsigned int)bytebuff_remaining(p_st_data))
        {
            /* 跳过参数名 */
            bytebuff_skip(p_st_data, ui_name_len);
            i_ret = APM_L7_ANALYZE_SUCC;
        }
    }

    /* 参数名称长度不足或者StatusFlags长度不足 */
    if (i_ret != APM_L7_ANALYZE_SUCC
        || (bytebuff_remaining(p_st_data) < 1))
    {
        if (i_whole_flg == FR_YES)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        else
        {
            return APM_L7_ANALYZE_TODO;
        }
    }

    /* 取得StatusFlags */
    bytebuff_get_char(p_st_data, &u8_status_flag);
    /*
    * fByRefValue: 1 if the parameter is passed by reference(OUTPUT parameter)
    * OR 0 if parameter is passed by value
    */
    if (u8_status_flag & 0x01)
    {
        *p_i_ref_flg = MSSQL_OUTPUT_PARAM;
    }
    else
    {
        *p_i_ref_flg = MSSQL_INPUT_PARAM;
    }

    /* TDS解析数据类型 */
    i_ret = sqlserver_type_info_parse(p_st_data, i_whole_flg, MSSQL_RPC
                                     , p_i_may_tds_ver, &u8_data_type
                                     , &u8_precision, &u8_scale
                                     , &i_partlentype);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }

    /* 取得参数类型对应的值 */
    i_ret = sqlserver_get_type_varbyte(p_st_data, p_st_sess, i_whole_flg
                                       , u8_data_type, u8_precision
                                       , u8_scale, i_partlentype
                                       , pp_st_value);
    return i_ret;
}

/*******************************************************************************
*  FUNC     :  解析RPC parameter
*  ARGS     :  pp_inbuffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  i_get_value_flg(是否需要取出具体的值)
*           :  p_i_may_tds_ver(可能的TDS版本号)
*           :  pp_st_value(参数值)
*           :  p_i_ref_flg(该参数是入参还是出参)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :  当i_get_value_flg设置成FR_NO时不需要释放内存，
*              当i_get_value_flg设置成FR_YES时并且返回值是
*              FR_SUCC时，假如pp_param_name，pp_param_value不是
*              NULL的时候需要释放内存。
*******************************************************************************/
int sqlserver_skip_rpc_param(Frbyte_Packet *p_st_data
                             , int i_whole_flg
                             , int *p_i_may_tds_ver
                             , int *p_i_ref_flg)
{
    int i_ret = APM_L7_ANALYZE_TODO;
    uint8_t u8_name_len = 0;
    unsigned int ui_name_len = 0;
    uint8_t u8_status_flag = 0;
    uint8_t u8_data_type = 0;
    uint8_t u8_precision = 0;
    uint8_t u8_scale = 0;
    int i_partlentype = FR_NO;

    /* 取得参数名称(TDS定义：B_VARCHAR = BYTELEN *CHAR) */
    if (bytebuff_remaining(p_st_data))
    {
        /* 此处的长度是实际UTF-8时的长度，故实际所占据packet的位数是长度的2倍 */
        bytebuff_get_char(p_st_data, &u8_name_len);
        ui_name_len = u8_name_len * 2;
        if (ui_name_len <= (unsigned int)bytebuff_remaining(p_st_data))
        {
            /* 跳过参数名 */
            bytebuff_skip(p_st_data, ui_name_len);
            i_ret = APM_L7_ANALYZE_SUCC;
        }
    }

    /* 参数名称长度不足或者StatusFlags长度不足 */
    if (i_ret != APM_L7_ANALYZE_SUCC
        || (bytebuff_remaining(p_st_data) < 1))
    {
        if (i_whole_flg == FR_YES)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        else
        {
            return APM_L7_ANALYZE_TODO;
        }
    }

    /* 取得StatusFlags */
    bytebuff_get_char(p_st_data, &u8_status_flag);
    /*
    * fByRefValue: 1 if the parameter is passed by reference(OUTPUT parameter)
    * OR 0 if parameter is passed by value
    */
    if (u8_status_flag & 0x01)
    {
        *p_i_ref_flg = MSSQL_OUTPUT_PARAM;
    }
    else
    {
        *p_i_ref_flg = MSSQL_INPUT_PARAM;
    }

    /* TDS解析数据类型 */
    i_ret = sqlserver_type_info_parse(p_st_data, i_whole_flg, MSSQL_RPC
                                     , p_i_may_tds_ver, &u8_data_type
                                     , &u8_precision, &u8_scale
                                     , &i_partlentype);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }

    /* 取得参数类型对应的值 */
    i_ret = sqlserver_skip_type_varbyte(p_st_data, i_whole_flg
                                        , u8_data_type, u8_scale
                                        , u8_precision, i_partlentype);
    return i_ret;
}

/*******************************************************************************
*  FUNC     :  做成request
*  ARGS     :  u8_packet_type(TDS的packet类型)
*  RTN      :  非NULL       (normal)
*              NULL         (error)
*  NOTE     :
*******************************************************************************/
L7_req_sqlserver* slqserver_create_request(uint8_t u8_packet_type)
{
    L7_req_sqlserver *p_st_req = NULL;

    /* 申请request */
    p_st_req = (L7_req_sqlserver *)frmalloc(sizeof(L7_req_sqlserver));
    if (p_st_req == NULL)
    {
        return NULL;
    }

    /* 初始化 */
    memset(p_st_req, 0x0, sizeof(L7_req_sqlserver));
    /* 设置类型 */
    p_st_req->u8_request_type = u8_packet_type;
    p_st_req->u8_packet_type = u8_packet_type;
    p_st_req->i_need_req_resp = MSSQL_REQUEST;

    return p_st_req;
}

/*******************************************************************************
*  FUNC     :  Frbindata结构体释放
*  ARGS     :  pp_st_frdata(Frdata_field结构体)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void sqlserver_frbindata_destory(Frbindata **pp_st_frbindata)
{
    if (pp_st_frbindata == NULL || *pp_st_frbindata == NULL)
    {
        return;
    }

    Frbindata *p_st_frbindata = *pp_st_frbindata;
    sqlserver_free((void **)&(p_st_frbindata->p_data));
    frfree(p_st_frbindata);

    *pp_st_frbindata = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  Frdata_field结构体释放
*  ARGS     :  pp_st_frdata(Frdata_field结构体)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void sqlserver_frdata_destory(Frdata_field **pp_st_frdata)
{
    if(pp_st_frdata == NULL || *pp_st_frdata == NULL)
    {
        return;
    }

    Frdata_field *p_st_frdata = *pp_st_frdata;
    /* 释放参数名称 */
    sqlserver_free((void **)&p_st_frdata->p_field_name);
    /* 释放参数值 */
    sqlserver_free((void **)&p_st_frdata->p_field_value);
    /* 释放本身 */
    frfree(p_st_frdata);

    *pp_st_frdata = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  删除对应sequence id的结果集
*  ARGS     :  p_st_statement (statement)
*           :  l_cursor_id (cursor id)
*  RTN      :  节点指针 (normal)
*               NULL    (error)
*  NOTE     :
*******************************************************************************/
void sqlserver_del_specified_cursor(Frlist_header *p_list_cursor
                                    , long l_cursor_id)
{
    Frlist_node *p_st_node_del = NULL;
    Frlist_node *p_st_node_pre = NULL;
    Frlist_node *p_st_node_curr = NULL;
    Mssql_cursor *p_st_cursor = NULL;

    p_st_node_curr = FRLIST_FIRST_NODE(p_list_cursor);
    /* 遍历list */
    while (p_st_node_curr)
    {
        p_st_cursor = (Mssql_cursor *)FRLIST_GET_NODE_DATA(p_st_node_curr);
        /* 删除本节点 */
        if (p_st_cursor->l_cursor_id == l_cursor_id)
        {
            /* 该node是最后一个节点,需要设置tail */
            if (p_st_node_curr->next == NULL)
            {
                p_list_cursor->tail = p_st_node_pre;
            }

            /* 要删除的节点是头结点 */
            if (p_st_node_pre == NULL)
            {
                p_st_node_del = frlist_remove_head(p_list_cursor);
                break;
            }
            else
            {
                p_list_cursor->size -= 1;
                p_st_node_pre->next = p_st_node_curr->next;
                p_st_node_del = p_st_node_curr;
                break;
            }
        }

        /* 取得下一个node */
        p_st_node_pre = p_st_node_curr;
        p_st_node_curr = FRLIST_NEXT_NODE(p_st_node_curr);
    }

    /* 释放节点 */
    if (p_st_node_del)
    {
        frfree(p_st_node_del->data);
        frfree(p_st_node_del);
    }
    else
    {
        frdbg("No matching node\n");
    }

    return;
}

/*******************************************************************************
*  FUNC     :  删除对应sequence id的结果集
*  ARGS     :  p_st_statement (statement)
*           :  l_prepare_id (prepare id)
*  RTN      :  节点指针 (normal)
*               NULL    (error)
*  NOTE     :
*******************************************************************************/
void sqlserver_del_specified_cursor2(Frlist_header *p_list_cursor
                                    , long l_prepare_id)
{
    Frlist_node *p_st_node_del = NULL;
    Frlist_node *p_st_node_pre = NULL;
    Frlist_node *p_st_node_curr = NULL;
    Mssql_cursor *p_st_cursor = NULL;

    p_st_node_curr = FRLIST_FIRST_NODE(p_list_cursor);
    /* 遍历list */
    while (p_st_node_curr)
    {
        p_st_cursor = (Mssql_cursor *)FRLIST_GET_NODE_DATA(p_st_node_curr);
        /* 删除本节点 */
        if (p_st_cursor->l_prepare_id == l_prepare_id)
        {
            /* 该node是最后一个节点,需要设置tail */
            if (p_st_node_curr->next == NULL)
            {
                p_list_cursor->tail = p_st_node_pre;
            }

            /* 要删除的节点是头结点 */
            if (p_st_node_pre == NULL)
            {
                p_st_node_del = frlist_remove_head(p_list_cursor);
                break;
            }
            else
            {
                p_list_cursor->size -= 1;
                p_st_node_pre->next = p_st_node_curr->next;
                p_st_node_del = p_st_node_curr;
                break;
            }
        }

        /* 取得下一个node */
        p_st_node_pre = p_st_node_curr;
        p_st_node_curr = FRLIST_NEXT_NODE(p_st_node_curr);
    }

    /* 释放节点 */
    if (p_st_node_del)
    {
        frfree(p_st_node_del->data);
        frfree(p_st_node_del);
    }
    else
    {
        frdbg("No matching node\n");
    }

    return;
}

/*******************************************************************************
*  FUNC     :  根据cursor ID取得对应的cursor信息
*  ARGS     :  p_st_statement (statement)
*           :  l_cursor_id (cursor id)
*  RTN      :  (Mssql_cursor *)
*  NOTE     :
*******************************************************************************/
Mssql_cursor* sqlserver_get_cursor_info(Frlist_header *p_list_cursor
                                       , long l_cursor_id)
{
    Frlist_node *p_st_node = NULL;
    Mssql_cursor *p_st_cursor = NULL;

    /* 取得头结点 */
    p_st_node = FRLIST_FIRST_NODE(p_list_cursor);
    /* 遍历list */
    while (p_st_node)
    {
        /* 取得源data */
        p_st_cursor = (Mssql_cursor *)FRLIST_GET_NODE_DATA(p_st_node);
        if (p_st_cursor && p_st_cursor->l_cursor_id == l_cursor_id)
        {
            return p_st_cursor;
        }
        /* 取得下一个节点 */
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }

    return NULL;
}

/*******************************************************************************
*  FUNC     :  判断sql语句是否是select
*  ARGS     :  p_sql (sql语句)
*  RTN      :  1       (true)
*              0       (false)
*  NOTE     :
*******************************************************************************/
int sqlserver_select_chk(const char *p_sql)
{
    if (p_sql == NULL)
    {
        return FR_NO;
    }

    /* 跳过字符串开头的空白字符 */
    while (*p_sql)
    {
        if (*p_sql == ' ' || *p_sql == '\t' || *p_sql == '\r' || *p_sql == '\n')
        {
            p_sql++;
            continue;
        }
        else
        {
            break;
        }
    }

    /* 判断是否是select, 不区分大小写 */
    if (strncmp(p_sql, "select", 6))
    {
        return FR_NO;
    }

    /* select之后必须有一个空白字符 */
    p_sql += 6;
    if (*p_sql == ' ' || *p_sql == '\t' || *p_sql == '\r' || *p_sql == '\n')
    {
        return FR_YES;
    }
    else
    {
        return FR_NO;
    }
}

/*******************************************************************************
*  FUNC     :
*  ARGS     :  p_st_conn (connect ct)
*           :  p_st_sess (session info)
*  RTN      :  (Mssql_cursor *)
*  NOTE     :
*******************************************************************************/
Frreport_body_data* sqlserver_new_report_body(Conntrack *p_st_conn
                                             , L7session_sqlserver *p_st_sess)
{
    int i_ret = FR_SUCC;
    Frreport_body_data *p_st_sess_body = NULL;

    /* 创建report body */
    p_st_sess_body = frreport_body_new_l7(p_st_conn);
    if (p_st_sess_body == NULL)
    {
        return NULL;
    }
    /* 追加connection相关信息 */
    i_ret = frreport_body_l7_add_connInfo(p_st_sess_body, p_st_conn);
    if (i_ret != FR_SUCC)
    {
        frreport_body_free(&p_st_sess_body);
        return NULL;
    }

    /* add server */
    if (p_st_sess->p_program)
    {
        i_ret = frreport_body_l7_add_str(p_st_sess_body
                                         , APM_REPORT_KEY_SESSION_SERVER
                                         , p_st_sess->p_program);
        if (i_ret != FR_SUCC)
        {
            frreport_body_free(&p_st_sess_body);
            return NULL;
        }
    }
    /* add username */
    if (p_st_sess->p_db_user)
    {
        i_ret = frreport_body_l7_add_str(p_st_sess_body
                                         , APM_REPORT_KEY_SESSION_USERNAME
                                         , p_st_sess->p_db_user);
        if (i_ret != FR_SUCC)
        {
            frreport_body_free(&p_st_sess_body);
            return NULL;
        }
    }
    /* add dbname */
    if (p_st_sess->p_db_name)
    {
        i_ret = frreport_body_l7_add_str(p_st_sess_body
                                         , MSSQL_REPORT_KEY_DBNAME
                                         , p_st_sess->p_db_name);
        if (i_ret != FR_SUCC)
        {
            frreport_body_free(&p_st_sess_body);
            return NULL;
        }
    }
    if (p_st_sess->st_login.tv_sec != 0
        || p_st_sess->st_login.tv_usec != 0)
    {
        /* add request start time */
        i_ret = frreport_body_l7_add_timeval(p_st_sess_body
                                            , APM_REPORT_KEY_SESSION_LOGIN_TIMESTAMP
                                            , &p_st_sess->st_login);
        if (i_ret != FR_SUCC)
        {
            frreport_body_free(&p_st_sess_body);
            return NULL;
        }
    }

    return p_st_sess_body;
}
